PROG3-A中出现了一些新的"面孔",下面分别引见给大家:
当使用DEBUG编制汇编程序时,摆在程序员面前的不仅仅是需要由程序控制的计算机硬件,同时还有为我们提供服务的软件--DEBUG。所以我们通过键盘输入的不但有控制硬件动作的"指令"(MOV、JMP),还有要求DEBUG给与帮助的"命令"(A、RBX)。而"伪指令"恰好是"指令"与"命令"的结合体。
从应用形式上看,它是和指令写在一起的,而不象DEBUG的命令那样打在提示符后;然而它的作用却和"命令"一样,要求DEBUG为我们做事情。也就是说CPU并不真正执行它,而执行它的是DEBUG。
现在我们来讨论出现在程序中的第一个伪指令──DB。
DB(Define Byte)的作用是命令DEBUG将给出的数据放入内存中。数据有两种形式──字符和数字,如果我们需要DEBUG把一些字符的ASCII码放入内存,则可以在这些字符两侧加上单引号,置于DB之后,如DB 'ABCD';如果需要DEBUG把一些16进制数字放入内存,则只需在DB后打出这些数字即可,如DB 'A',42,43,44。要注意的是字符与数字,数字与数字之间的逗号不可丢掉。
所有数据在内存中都是连续存放的,DB前面的逻辑地址(09FE:0102)就是这一串数据的"首地址"。DB后面指令的逻辑地址由DEBUG自动算出。
在PROG3-A中,我们用数字0表示字符串结束,因此在输出字符时,只要判断取到DL中的数据是否为0,即可知道是否已经输出了所有的字符。程序中使用了两条指令完成判断工作,第一条是:
助记符:CMP(Compare)
用 途:比较两个数据的大小
格 式:CMP 寄存器,立即数
CMP 寄存器,寄存器
CMP 寄存器,存储单元
CMP 存储单元,寄存器
CMP 存储单元,立即数
执 行:CPU将两个待比较的数据做一次减法,结果不保留,但"后果"由标
志寄存器记录。
使用CMP指令时要注意这样一点,就是相比较的两个数据位宽要一致,即8位寄存器只能和8位立即数或寄存器相比较,也只能和存储器中的一个字节数据相比,下面这样的用法是不对的--"CMP AL,0FFFH"、"CMP AH,BX"
CPU执行CMP指令的实际动作是用左边的数据减右边的数据,但减的结果并不保留在左边的寄存器或存储器中,如果相比较的两个数据相等,那么"相减"后结果必为0,所以相等的两个数比较,将使ZF标志置1。要想判断两个数据是否相等,只需在CMP指令后用JZ/JNZ指令根据ZF的状态进行相应转移即可。
为便于记忆,我们给JZ/JNZ指令赋与了一个新的写法--JE/JNE(Jump if Equal/Not Equal)。因此指令"JZ 124"也可写成"JE 124"。
前面我们讨论过用BX寄存器作指针的一种间接寻址方式,用那种寻址方式时我们要把字符串的首地址直接放入BX寄存器以建立指针。而在PROG3-A中,我们在BX寄存器中装入的是每一个数据相对首地址的偏移量。在取数据时用这个偏移量加上字符串的首地址作为数据的实际偏移地址。这种寻址方式称为"寄存器相对寻址方式"(Register relative addressing)。
这两个程序都是用BX作指针,能否用其它通用寄存器呢?注意对于8086/88CPU而言,可做间接寻址的通用寄存器只有BX,其它三个通用寄存器无此功能。我们后面说到"串处理"时会介绍更多的可做间接寻址的寄存器,但它们都不是通用寄存器了。
-a100[Enter] 09FE:0100 jmp 111 ;跳过字符串数据区 09FE:0102 db'Hello,World!',0d,0a,'$' ;定义一个字符串,结尾为"$" 09FE:0111 mov dx,102 ;DX寄存器指向字符串首地址 09FE:0114 mov ah,9 ;选择DOS API的09H功能 09FE:0116 int 21 ;调用21H中断显示字符串 09FE:0118 int 20 ;调用20H中断结束程序,返回DOS 09FE:011A [Enter]
PROG3-B编写得非常短小,但却和PROG3-A有相同的效果,原因在于这个程序使用了操作系统提供的一个极常用的功能──09H(显示字符串)。
功能号:09H
用 途:显示字符串
参 数:AH=09H
DX=字符串的首地址
调 用:INT 21H
返 回:无
09功能要求字符串必须以'$'结尾。调用此功能前应将字符串的首地址放入DX寄存器,然后执行INT 21H即可。此功能同样解释0DH,0AH等控制码。