[BX]代表什么?我们先看一下这两个语句:
mov ax, [0]:意思是将一个内存单元的内容送入ax里,这个内存单元的长度为2字节,存放一个字,偏移地址是0,段地址在ds中。
mov al, [0]:意思是将一个内存单元的内容送入ax里,这个内存单元的长度为1字节,存放一个字节,偏移地址是0,段地址在ds中。
由此可见,要完整的描述一个内存单元,需要两种信息:
(1)内存单元的地址。
(2)内存单元的长度。
因此,**[bx]**是一个内存单元,它的偏移地址在bx中,段地址在ds中,具体大小看具体情况。
这里再定义一个描述性符号:“()”表示一个寄存器或一个内存单元中的内容。
例如:(ax)表示ax中的内容,(20000H)表示内存20000H单元的内容,(ds)表示段地址的内容。
还有一个约定符号idata,表示常量。举个例子,mov ax, idata意思为mov ax, 1、mov ax, 2、mov ax, 3……。
5.1 [BX]
这里有两个重要的指令:
mov ax, [bx]:意思是把ds:bx内存单元的内容送入ax中。
mov [bx], ax:意思是把ax的内容送到ds:bx中。
还有一个新的指令:
inc:inc ax意思是ax=ax+1。
5.2 Loop指令
loop指令的格式是:loop+标号。
CPU通过两步操作执行loop指令:
(1)(cx)=(cx)-1
(2)判断cx中的值是否为零,不是零则转移至标号处继续执行,是零则向下执行。
我们要编程计算2^12,一个方式就是设ax=2,然后使用add指令计算22222222222*2,显然这个方法略显复杂。
还有一个方式就是使用loop,循环12次,代码是这样的:
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)在cx中存放循环次数
(2)Loop指令的标号所标识地址要写在前面
(3)要循环的代码段在标号和loop指令中间
5.3 在Debug中跟踪用loop指令实现的循环程序
这里有一个小优化:如果要使用循环计算123*456,可以是123+123循环456遍,也可以是456+456循环123遍,当然后者循环次数少,更加高效。
引出两个命令:
p命令:遇到loop时,使用p命令会跳过循环的代码,直接运行到cx=0的地方。
g命令:直接使用g命令可以让代码运行完,也可以使用g 0016类似的断点的格式,让代码运行到CS:0016处停下。
5.4 Debug和汇编编译器masm对指令的不同处理
在汇编程序中,使用“[]”前面需要给出段地址所在的段寄存器,否则**[idata]**会被当解释为idata,例如:mov al, ds:[0],而不能:mov al, [0]。
如果在“[]”中用寄存器,间接给出内存单元的偏移地址,则段地址默认在ds中。
5.5 loop和[bx]的联合应用
求ffff:0~ffff:b单元中的数据的和,结果存储在dx中的程序:
assume cs:code
code segment
mov ax, 0ffffh
mov ds, ax
mov bx, 0
mov ds, 0
mov cx, 12
s: mov al, [bx]
mov ah, 0
add dx, ax
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end
编程中经常会遇到使用同一种方法处理地址连续的内存单元中的数据的问题,需要用循环来解决这一问题,同时在每一次循环中按照同一方式改变想要访问的内存单元的地址。例如“mov al,[bx]”中的通过改变bx的值,改变指令访问的内存单元。
5.6 段前缀
mov ax, ds:[bx]意思是将一个内存空间的内容送入ax,这个内存空间的长度为2字节,存放一个字,编译地址在bx中,段地址在ds中。
像这样出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:” “cs:” “ss:” “es:”在汇编语言中称为段前缀。
5.7 一段安全的空间
在不确定一段内存空间中是否存放着重要的数据或代码的时候,不能随意向其中写入内容。
如果需要直接向一段内存中写入内容,这段内存空间不应存放系统或其他程序的数据和代码,否则写入很可能会引发错误。在DOS方式下,一般情况,0:200~0:2ff空间中没有系统或其他程序的数据或代码,可以直接写入内容。
5.8 段前缀的使用
求将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中。
assume cs:code
code segment
mov ax, 0ffffh
mov ds, ax
mov ax, 0020h
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
使用ds和es分别存放两个空间的段地址,显式地使用段前缀给出单元的段地址。