[bx]是什么呢?
和[0]有些类似,[0]代表内存单元,它的偏移地址是0.
我们要完整的描述一个内存单元,需要两种信息:
1)内存单元的地址
2)内存单元的长度(类型)
我们用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出。
[bx]同样也表示一个内存单元,它的偏移地址在bx中,比如下面的指令:
mov ax,[bx]
mov al, [bx]
loop
英文单词loop有循环的含义,显然这个指令和循环有关。
描述性符号()
为了描述上的简洁,在以后的课程中,我们将使用一个描述性的符号()来表示一个寄存器或一个内存单元中的内容。
我们看一下(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
约定符号idata表示常量
我们在debug中写过类似的指令:
mov ax,[0] ,表示将ds:0处的数据送入ax中。指令中,在[,,,]里用一个常量0表示内存单元的偏移地址。以后,我们用idata表示常量。
5.1[bx]
我们看一看下面指令的功能:
mov ax,[bx]
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入ax中。
即:(ax)=(ds*16+(bx));
mov [bx],ax
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入内存SA:EA处。
5.2 loop指令
指令的格式是:loop标号,CPU执行loop指令的时候,要进行两步操作:
1)(cx)=(cx)-1;
2)判断cx中的值,不为零则转至标号处执行程序,如果为0则向下执行
程序分析:
1)标号
在汇编语言中,标号代表一个地址,此程序中有一个标号s。它实际上标识了一个地址,这个地址处有一条指令:add ax,ax
2)loop s
CPU执行loop s的时候,要进行两步操作:
1)(cx)=(cx)-1
2)判断cx中的值,不为0则转至标号s所指标识的地址处执行,如果为0则执行下一条指令。
用cx和loop指令相互配合实现循环功能的程序框架如下:
mov cx,循环次数
s:
循环执行的程序段
loop s
debug中的G命令:在单步执行时,可以直接跳到指定地址
debug中的p命令:单步执行程序时,可以跳过loop的循环,类似c语言中的continue
5.4 debug和汇编编译器masm对指令的不同处理
在汇编源程序中,指令mov ax,[0]被编译器当作指令mov ax,0处理
5.5 loop和[bx]的联合应用
首先分析计算结果会不会超出dx所能存储的范围
因为ffff:0到ffff:b内存单元中的数据是字节型数据,范围在0~255之间,12个这样的数据相加,结果不会大于65535,可以在dx中存放下。
但我们不能直接累加,因为ffff:0~ffff:b中的数据是8位的不能直接加到16位的寄存器dx中。
我们也不能将ffff:0~ffff:b中的数据累加到dl中,并设置dh=0,因为dl是8位寄存器,能容纳的数据范围小于255,12个0~255之间的数累加存进dx中,很有可能造成进位丢失。
在实际编程中,经常会遇到,用同一种方法处理地址连续的内存单元中的数据的问题。
我们需要用循环来解决这类问题,同时我们必须能够在每次循环的时候按照同一种方法来改变要访问的内存单元的地址。
5.6 段前缀
指令mov ax , [bx]中,内存单元的偏移地址由bx给出,而段地址默认在ds中。
我们可以在访问内存单元的指令中显式地给出内存单元地段地址所在地段寄存器。
这些出现在访问内存单元地指令中,用于显式地指令内存单元的段地址的ds、cs、ss、es,在汇编语言中称为段前缀。
5.8 段前缀的使用
我们考虑一个问题:
将内存ffff:0~ffff:b单元中的数据拷贝到0:200~0:20b单元中
分析一下:
0:200~0:20b单元等同于0020:0~0020:b单元,他们描述的是同一段内存空间。
因源单元ffff:x和目标单元0020:x相距大于64KB,在不同的64KB段里,程序中,每次循环要设置两次ds。
这样效率不高。
我们可以使用两个段寄存器分别存放源单元ffff:x和目标单元0020:x的段地址,这样就可以省略循环中需要重复做12次的设置ds的程序段。