<1>[BX]

想要完整地描述一个内存单元,需要两种信息:(1)内存单元的地址(2)内存单元的长度(类型)。[BX]和[0]有些相似,表示一个内存单元,它的偏移地址在bx中。指令mov ax,[bx]的功能为将bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入ax中,即(ax)=((ds)*16+(bx))。ps:此处的()表示的为括号内寄存器或者内存单元的内容。

<2>Loop指令

loop在英语中有循环的含义,所以这个指令应该和循环有关。loop指令的格式:loop 标号,这里的标号指明了循环开始的地方。CPU执行loop指令的时候,要进行两步操作:(1)(cx)=(cx)-1(2)判断cx中的值,如果不为零则转至标号处执行程序,如果为零则向下执行。经过书上所给示例的实践,可以总结出用cx和loop指令相配合实现循环功能的3个要点:(1)在cx中存放循环次数(2)loop指令中的标号所标识的地址要在前面(3)要循环执行的程序段,要写在标号和loop指令的中间。

<3>Debug和汇编编译器masm对指令的不同处理

 在Debug中我们曾经使用过mov ax,[0]这样的指令,这条指令表示将ds:0处的数据送入寄存器ax中。但是在汇编的源程序中,指令“mov ax,[0]”被编译器当作指令“mov ax,0”来处理。经过实践我们可以看出Debug和编译器对这些指令中的“[idata]”解释的不同。Debug将其解释为“[idata]”是一个内存单元,“idata”为内存单元的偏移地址;而编译器将其解释为“idata”。我们如果想要实现在寄存器中访问内存单元,我们可以把偏移地址送入bx寄存器中,用[bx]的方式来访问内存单元。例如我们想要访问2000:0单元:mov ax,2000h;mov ds,ax;mov bx,0;mov al,[bx]经过验证上述方法能够实现目标。可是用[bx]间接地给出内存单元的偏移地址还是较为麻烦的,我们也可以在[ ]中直接给出内存单元的偏移地址,只不过要在[ ]的前面显式地给出段地址所在的段寄存器,例如我们还是要访问2000:0单元:mov ax,2000h;mov ds,ax;mov al,ds:[0]经过实践可以实现目标。

 

下面通过编程实践书上的示例、问题,来对这章的内容有更深层次的理解。

(1)p100示例

iotop命令输出详解 loop指令的功能_寄存器

上述代码所实现的是计算2^12,使用11条重复的add ax,ax指令能够达成目标可是太过于繁琐,而使用循环指令loop能够很好的简化程序,下面我们对循环程序进行跟踪。

iotop命令输出详解 loop指令的功能_iotop命令输出详解_02

使用u指令查看程序对应的汇编指令以及其在内存的存储情况,并用g指令执行到程序返回之前,在执行之后可以看到结果送入寄存器ax值为1000h即2^12,实现了目标。

(2)p102示例

iotop命令输出详解 loop指令的功能_数据_03

上述的代码所要实现的是用加法实现123*236,结果存入寄存器ax中,下面对程序进行跟踪。

 

iotop命令输出详解 loop指令的功能_iotop命令输出详解_04

执行和(1)相同的操作可以看到寄存器ax在程序执行到返回前后的值为7164h即29028,实现了目标。在这个实验中如果我们将236加123次,可以用123次加法实现相同的目标,提高了计算的速度。