1.关于[bx]
1)[bx]用来表示取寄存器bx中的值作为偏移地址;
段地址保存在段寄存器ds中;
例如:将 2000:1000 处的数据保存到寄存器ax
mov ax,2000
mov ds,ax
mov bx,1000
mov ax,[bx]
2)指令inc
inc 为自增指令;
例如:将寄存器bx中的值自增1
inc bx
3)debug和masm对指令的不同处理
例如:想将1000:1处的值存入ax
在debug中代码如下:
mov ax,1000
mov ds,ax
mov ax,[1]
这里的 mov ax,[1]中的[1]表示偏移地址为1,段地址取段寄存器ds中的值;
而用masm编译时不会将[1]识别为偏移地址,而是当做常量1;
也就是说masm将mov ax,[1] 当作mov ax,1 ,作用是将ax中的值设为1;
为了达到原来的目的,可以用[bx];
代码:
mov ax,1000
mov ds,ax
mov bx,1
mov ax,[bx]
如果一定要用常量表示偏移地址,需要显式给出段寄存器
mov ax,1000
mov ds,ax
mov ax,ds:[1]
显式给出段寄存器时,该段寄存器称为段前缀;
段前缀默认是ds:
也可以用cs:、es、ss等代替;
4)段前缀的使用
例如:想要将 ffff:0~ffff:b中的数据复制到 20:0~20:b;
思路:
将偏移地址放入bx;
循环12次,每次bx中的值自增1,并且通过一个中转寄存器保存待复制数据;
但这样涉及到一个问题:
数据的段地址默认保存在段寄存器ds中;
在每次复制中,需要设置两次ds的值:ffff和20;
可以利用其它段寄存器分别存放两个段地址来解决这一问题,利用段前缀可指定段地址;
代码:
assume cs:code
code segment
mov ax,ffff
mov ds,ax
mov ax,20
mov es,ax
mov bx,0
mov cx,12
s: mov dl,[bx]
mov es:[bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
2.loop指令
loop指令用来做循环操作;
loop的执行分为两步:
1】寄存器cx中的值减1;
2】判断cx中的值是否为0,不为0则跳转到标号处,为0则继续向下执行;
指令格式为:loop 标号;
标号是自定义的标记,用来标记特定指令的位置;
例如:计算2的3次方
assume cs:demo
demo segment
mov ax,2
mov cx,2
s: add ax,ax
loop s
mov ax,4c00h
int 21h
demo ends
end
3.loop和[bx]联合使用
例如:要实现 ffff:0-ffff:b中的数据累加,并将结果存入寄存器dx;
分析:
1】每个内存单元数据为一个字节,而寄存器dx为一个字,无法直接计算;
2】如果用dx的低位dl则可能超出dl的容量,累加后的结果可能超出8位;
3】每一个字节的最大值为255,0-b有13个数,累加结果不会超过16位的25536,因此dx足够可以存放;
4】可以用寄存器ax作为中介来实现字节和字之间的转换:将目标值存入al,ah设置为0,然后将ax的值累加到dx中;
代码:
assume cs:demo
code demo
mov ax,ffff
mov dx,ax
mov bx,0
mov dx,0
mov cx,12
s: mov ah,0
mov al,[bx]
add dx,ax
inc bx
loop s
mov ax,4c00h
int 21h
demo ends
end
4.安全空间
利用汇编指令直接向内存写入数据时,可能这段内存中保存有系统或其它程序的代码;
此时写入操作可能引发错误;
因为操作系统管理内存资源,如果需要向内存中写入数据时,要使用操作系统给我们分配的空间,而不应该随意指定内存地址;
在dos方式下,一般情况0:200~0:2ff空间不会有系统或其它程序的数据,通常可以直接使用该段空间;
为了谨慎起见,也可以用debug查询该段空间,如果单元内容都是0则表示该段内存单元没有被使用;