一、[bx]和内存单元的描述
1、[bx]是什么呢?
和[0]有些类似,[0]表示内存单元,它的偏移地址是0。
mov ax, [0] 字单元
mov al, [0] 字节单元
我们要完整地描述一个内存单元,需要两种信息:
(1)内存单元的地址;
(2)内存单元的长度(类型)。
我们用[0]表示一个内存单元时,0 表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出,如前边的AX,AL。
[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:
mov ax,[bx] 如果 mov ax,[0]编译器会认为是 mov ax,0而不是0偏移地址的地址,所以需要先mov bx,0 再mov ax,[bx]
mov al,[bx]
1、描述性符号“()”:为了描述上的简洁,在以后的课程中,我们将使用一个描述性的符号 “() ”来表示一个寄存器或一个内存单元中的内容。
我们看一下(X)的应用,比如:
(1)ax中的内容为0010H,我们可以这样来描述:(ax)=0010H;
(2)2000:1000 处的内容为0010H,我们可以这样来描述:(21000H)=0010H;
(3)对于mov ax,[2]的功能,我们可以这样来描述:(ax)=((ds)16+2);
(4)对于mov [2],ax 的功能,我们可以这样来描述:((ds)16+2)=(ax);
(5)对于 add ax,2 的功能,我们可以这样来描述:(ax)=(ax)+2;
(6)对于add ax,bx的功能,我们可以这样来描述:(ax)=(ax)+(bx);
(7)对于push ax的功能,我们可以这样来描述: (sp) = (sp)-2
((ss)16+(sp))=(ax)
(8)对于pop ax 的功能,我们可以这样来描述:
(ax)=((ss)16+(sp)) (sp)=(sp)+2
我们在Debug 中写过类似的指令:mov ax,[0],表示将 ds:0 处的数据送入ax中。指令中,在“[…]”里用一个常量0表示内存单元的偏移地址。以后,我们用idata表示常量。
例如:
mov ax,[idata]就代表mov ax,[1]、mov ax,[2]、mov ax,[3]等。
mov bx,idata就代表mov bx,l、mov bx,2、mov bx,3等。
mov ds,idata就代表mov ds,1、mov ds,2等,它们都是非法指令。
[bx]:
mov ax,[bx]
功能:bx 中存放的数据作为一个偏移地址EA ,段地址SA 默认在ds 中,将SA:EA处的数据送入ax中。
即: (ax)=((ds) *16 +(bx));
二、loop(循环)
指令的格式是:loop 标号,CPU 执行loop指令的时候,要进行两步操作:
① (cx)=(cx)-1;
② 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
从上面的描述中,我们可以看到,cx中的值影响着loop指令的执行结果。
通常(注意,我们说的是通常)我们用loop指令来实现循环功能,cx 中存放循环次数。
程序代码:
assume cs:code
code segment
mov ax,2
mov cx,11
s: add ax,ax
loop s
mov ax,4c00h
int 21h
code ends
end
(1)标号在汇编语言中,标号代表一个地址,此程序中有一个标号s 。它实际上标识了一个地址,这个地址处有一条指令:add ax,ax。
(2)loop s
CPU 执行loop s的时候,要进行两步操作:
① (cx)=(cx)-1;
② 判断cx 中的值,不为0 则转至标号s 所标识的地址处执行(这里的指令是“add ax,ax),如果为零则执行下一条指令(下一条指令是mov ax,4c00h)。
注意程序中的第一条指令mov ax,0ffffh。
我们知道大于9FFFH的十六进制数据A000H、A001H、…… 、C000H、C001H、……、FFFEH、FFFFH等,在书写的时候都是以字母开头的。
而在汇编源程序中,数据不能以字母开头,所以要在前面加0。
三、温故而知新
【bx】的作用:作为偏移地址与DS配合
loop和cx合作
debug的-g 偏移地址 命令 和 -p命令
四、Debug和汇编编译器Masm对指令的不同处理
我们在Debug中写过类似的指令:
mov ax,[0]
表示将ds:0处的数据送入al中。
但是在汇编元程序中,指令“mov ax,[0]”被编译器当作指令“mov ax,0”处理。
在MASM中mov ax, [2]是解释为mov ax,2的。一般我们是通过BX来代替,像这道题我们先mov bx, 2 再通过mov ax, [bx]来实现。
但是我们要像DEBUG一样直接用[2]可以吗?答案是……
可以的,不过要加上段地址!!试试!
mov ax,ds[0]
五、loop和[bx]的联合应用
计算ffff:0~ffff:b单元中的数据的和,结果存储在dx中。
在实际编程中,经常会遇到,用同一种方法处理地址连续的内存单元中的数据的问题。
我们需要用循环来解决这类问题,同时我们必须能够在每次循环的时候按照同一种方法来改变要访问的内存单元的地址。
六、段前缀
指令“mov ax,[bx]”中,内存单元的偏移地址由bx给出,而段地址默认在ds中。
我们可以在访问内存单元的指令中显式地给出内存单元的段地址所在的段寄存器
这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”、“cs:”、“ss:”或“es:”,在汇编语言中称为段前缀
七、一段安全的空间
在8086模式中,随意向一段内存空间写入内容是很危险的 ,因为这段空间中可能存放着重要的系统数据或代码。
比如下面的指令:
mov ax,1000h
mov ds,ax
mov al,0
mov ds:[0],al
在一般的PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用0:200~0:2FF( 0:200h~0:2FFh)的256 个字节的空间。所以,我们使用这段空间是安全的。
es附加段寄存器,csdsss不够用的时候用es