文章目录
- [BX]和loop指令
- 1 [bx]
- 2 Loop指令
- 3 在Debug中跟踪用loop指令实现的循环程序
- 4 Debug和汇编编译器Masm对指令的不同处理
- 5 loop和[bx]的联合应用
- 6 段前缀
- 7 一段安全的空间
- 8 段前缀的使用
[BX]和loop指令
1 [bx]
我们用[bx]表示一个内存单元,它的段地址默认在ds中,它的偏移地址在bx中,比如下面的指令:
mov ax,[bx]
mov al,[bx]
2 Loop指令
loop指令用于循环操作
指令的格式是:loop 标号
CPU 执行loop指令的时候,要进行两步操作:
① (cx)=(cx)-1;
② 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
用loop指令计算212:
assume cs:codecode segmentmov ax,2mov cx,11s: add ax,axloop smov ax,4c00hint 21hcode endsend
3 在Debug中跟踪用loop指令实现的循环程序
计算ffff:0006单元中的数乘以3,结果存储在dx中。
代码如下:
assume cs:abcabc segmentmov ax,0ffffhmov ds,axmov bx,6mov al,[bx]mov dx,0mov cx,3s: add dx,axloop smov ax,4c00hint 21habc endsend
在汇编源程序中,数据不能以字母开头,所以要在第四行的ffff前面加0。
可以用p
命令直接完成循环。
4 Debug和汇编编译器Masm对指令的不同处理
我们在Debug中写过类似的指令:
mov ax,[0]
表示将ds:0处的数据送入al中。
但是在汇编元程序中,指令“mov ax,[0]”被编译器当作指令“mov ax,0”处理,即编译器无法将[0]识别成一个内存地址,而是会将其当成数字。
这个问题有两种解决方案:
-
通过BX来代替[0],我们先mov bx, 2 再通过mov ax, [bx]来完成。
-
在偏移地址前加上段地址,即mov al, ds:[0]。
5 loop和[bx]的联合应用
计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。
代码如下:
assume cs:abcabc segmentmov ax,0ffffhmov ds,axmov bx,0mov dx,0mov cx,12s: mov al,[bx]add dx,axinc bxloop smov a,4coohint 21habc endsend
这时我们就不用能常量给出内存单元的地址,而是用bx作为内存单元地址的变量。
6 段前缀
这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”或“es:”,在汇编语言中称为段前缀。
7 一段安全的空间
在8086模式中,随意向一段内存空间写入内容是很危险的 ,因为这段空间中可能存放着重要的系统数据或代码。
在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200~0:2FF( 0:200h~0:2FFh)的256 个字节的空间。所以,我们使用这段空间是安全的。
以后,我们需要直接向一段内存中写入内容时,就使用0:200~0:2FF这段空间。
8 段前缀的使用
将内存ffff:0~ffff:b段元中的数据拷贝到 0:200~0:20b单元中。
代码一:
assume cs:abcabc segmentmov bx,0mov cx,12s: mov ax,0ffffhmov ds,axmov dl,[bx]mov ax,0020hmov ds,axmov [bx],dlinc bxloop smov a,4coohint 21habc endsend
因源单元ffff:X和目标单元0020:X 相距大于64KB,在不同的64KB段里,程序中,每次循环要设置两次ds。
这样做是正确的,但是效率不高。
我们可以使用两个段寄存器分别存放源单元ffff:X和目标单元0020:X的段地址,这样就可以省略循环中需要重复做12次的设置ds的程序段。
代码二:
assume cs:abcabc segmentmov ax,0ffffhmov ds,axmov ax,0020hmov es,axmov bx,0mov cx,12s: mov al,[bx]mov es:[bx],alinc bxloop smov a,4coohint 21habc endsend