2.3.1 数据传送指令
1.通用数据传送指令
数据传送指令可以实现数据、地址、标志的传送。除了目标地址为标志寄存器的传送指令外,本组的其他指令不影响标志,如表2-2所示。
表2-2 数据传送指令
(1)传送指令MOV。
格式:MOV DST,SRC
功能:SRC(源)→DST(目标)。
说明:MOV指令可以实现一个字节、一个字的数据传送,注意源操作数和目标操作数的数据类型匹配问题,即应同为字节或字型数据。
MOV指令可实现的数据传送方向如图2-9所示。
图2-9 MOV指令数据传送方向示意图
从图2-9中可以看出,
立即数不能作为目标操作数;
立即数不能直接送段寄存器;
目标寄存器不能是CS,因为随意修改CS会引起不可预料的结果;
两个段寄存器间不能直接传送;
两个存储单元之间不能直接传送。
在使用MOV指令时一定要遵守以上这些限制,否则汇编时会出错。
【例2-15】
MOV AL,5
MOV AX,BX
MOV BP,DS
MOV DS,AX
MOV[BX],AX
MOV ES:VAR,12
从例2-15中可以看出,MOV指令功能很强,使用不同的寻址方式,即可以汇编出数十条不同的机器指令。
(2)堆栈操作指令。
在第1章介绍过堆栈的基本概念,其中堆栈数据的存取原则是“后进先出”。在PC机中,栈基地址放在SS堆栈段寄存器中,栈顶地址放在SP堆栈指针寄存器中,SP始终指向栈顶。堆栈主要用于对现场数据的保护与恢复、子程序与中断服务返回地址的保护与恢复等。
①进栈指令PUSH。
格式:PUSH SRC
功能:先修改堆栈指针(在堆栈指针寄存器中)使其指向新的栈顶(若SRC是16位操作数则堆栈指针减2),然后把SRC压入(复制)到栈顶单元。
说明:SRC可以是16位的寄存器操作数或存储器操作数,不能是8位的操作数。
【例2-16】 若有以下指令(堆栈尺寸及操作数均为16位),其执行操作如图2-10所示。
PUSH AX
从图2-10中可以看出,随着PUSH指令条数的增加,栈中数据也随之增多,堆栈可用空间逐渐减少,若开辟的堆栈空间不够大,最终会导致堆栈溢出。因此程序设计者应注意堆栈的初始设置要足够大。
图2-10 PUSH指令执行情况
②出栈指令POP。
格式:POP DST
功能:先把堆栈指针所指向单元的内容弹出(复制)到DST,然后修改堆栈指针以指向新的栈顶(若SRC是16位操作数则堆栈指针加2)。
说明:DST可以是16位的寄存器操作数和存储器操作数,也可以是除CS寄存器以外的任何段寄存器。若DST是16位,则堆栈指针加2。
【例2-17】 若当前堆栈如图2-11(a)所示,现有以下指令序列(堆栈尺寸及操作数均为16位),则其执行操作如图2-11所示。
POP BX
POP AX
图2-11 POP指令执行情况
从图2-11中可以看出,随着POP指令条数的增加,SP的值也随之增加,堆栈可用空间逐渐加大。当SP的值已大于初始设置时,则出现堆栈异常。编程时应注意避免此类问题发生。
(3)交换指令XCHG。
格式:XCHG OPRl,OPR2
功能:交换两个操作数。
说明:OPR是操作数,操作数可以是8位、16位。该指令可能的组合如下:
XCHG 寄存器操作数,寄存器操作数
XCHG 寄存器操作数,存储器操作数
XCHG 存储器操作数,寄存器操作数
其他组合都是错误的。
【例2-18】 XCHG AX,BX
设(AX)=1234H,(BX)=0788H,指令执行后,
(AX)=0788H,(BX)=1234H
2.查表转换指令XLAT
格式:XLAT
功能:通过AL寄存器中的索引值在表中查得表项内容并返回到AL中。
说明:使用这条指令之前,数据段中应有一个字节型表,该表起始地址的偏移量应放入BX,表索引值放入AL。
【例2-19】 通过查表转换指令,把0~15之间的十进制数转换成十六进制数的ASCII值。
为了实现这个功能,需要先造一个十六进制数的ASCII值表,其顺序为0~9、A~F,如图2-12中的表格所示。
图2-12 十六进制数的ASCII值表
例如,要查11的十六进制数的ASCII值,编写如下程序段:
…
ASCTAB DB′0′,′1′,′2′,′3′,′4′,′5′,′6′,′7′,′8′,′9′,′A′,′B′,′C′,′D′,′E′,′F′;数据段
… ;代码段
MOV AX, SEG ASCTAB;取ASCTAB的段首地址
MOV DS, AX
MOV BX, OFFSET ASCTAB;取ASCTAB的偏移地址
MOV AL, 11
XLAT
…
可以看到,定义的表名为ASCTAB,用DB定义字节型数据,′0′为数字0的字符表示形式,在存储器中呈现为二进制数00110000。为了书写方便,用十六进制数表示为30H。通过SEG操作符把表所在的段基址送给DS,OFFSET操作符把表偏移量送给BX,把索引值11送给AL,执行XLAT指令后,AL中得到42H,它就是11的十六进制数的ASCII值。其执行结果如图2-12所示。通过改变AL中的索引值,可以查到不同的ASCII值。例如,若给AL送入数字9,则可以得到字符9的ASCII值39H。
3.地址传送指令
这类指令传送的是操作数的地址,而不是操作数本身,它有别于MOV指令。
(1)传送有效地址指令LEA。
格式:LEA REG,SRC
功能:把源操作数的偏移地址(有效地址)送给指定的寄存器。
注意:源操作数必须是存储器操作数,不允许其他操作数形式。
【例2-20】
LEA BX,ASCTAB;ASCTAB表示内存单元符号地址
LEA BX,ASCTAB[SI];把DS:[ASCTAB+SI]单元的偏移量送给BX
LEA DI,ASCTAB[BX][SI];把DS:[ASCTAB+BX+SI]单元的偏移量送给DI
LEA BX,VAR等价于“MOV BX,OFFSET VAR”指令。其中OFFSET是操作符(在第3章具体讲解)。注意这种情况只适用于LEA指令的源操作数为直接寻址方式时。
(2)加载数据段指针指令LDS。
格式:LDS REG,SRC
功能:把源操作数中的FAR型指针复制到DS和指令中指定的通用寄存器REG。
注意:源操作数必须是存储器操作数,目标寄存器应是一个16位通用寄存器。
【例2-21】 LDS SI,ADDR
若(DS:ADDR)=78563412H,则这条指令的执行结果是(DS)=7856H,(SI)=3412H,执行情况如图2-13所示。
图2-13 LDS SI,ADDR指令执行情况
(3)加载附加数据段指针指令LES。
格式:LES REG,SRC
功能:把源操作数中的FAR型指针复制到ES和指令中指定的通用寄存器REG。
注意:除了把指针中的高16位送给ES外,其他与LDS相同。
【例2-22】 LES DI,ADDR
若(DS:ADDR)=78563412H,则这条指令的执行结果是(ES)=7856H,(DI)=3412H,执行情况与图2-13所示的相似,只是两个寄存器不同而已。
4.标志传送指令
这组指令中的POPF、SAHF指令影响标志位,其他的不影响。
(1)16位标志进栈指令PUSHF。
格式:PUSHF
功能:先使堆栈指针寄存器SP减2,然后压入(复制)标志寄存器FLAG S的内容到栈顶单元。
(2)16位标志出栈指令POPF。
格式:POPF
功能:先把堆栈指针所指向的字弹出(复制)到FLAG S,然后使SP加2。
标志:影响FLAG S中的所有标志。
(3)标志送AH指令LAHF。
格式:LAHF
功能:标志寄存器低8位(FLAG S7~FLAG S0)内容送AH寄存器。
(4)AH送标志寄存器指令SAHF。
格式:SAHF
功能:AH寄存器内容送标志寄存器低8位(FLAG S7~FLAG S0)。
标志:影响FLAG S中的低8位标志。
5.输入/输出指令
由于8086/8088系统采用外设独立编址,所以指令系统提供了专门的输入、输出指令,它们专用于CPU与外设之间的数据传送。这两条指令的详细使用情况可参考第5章相关内容。
(1)输入指令IN。
格式:IN AL,PORT
IN AX,PORTIN AL,DXIN AX,DX
功能:把外设端口地址指出的内容传送给累加器AL或AX。
说明:可以传送8位、16位,相应的累加器选择AL、AX。若端口号在0~255之间,则端口号直接写在指令中;若端口号大于255,则端口号通过DX寄存器间接寻址,即端口号应先放入DX中。
【例2-23】
IN AL,6lH;把61H端口的内容(字节)输入到AL
IN AX,20H;把20H端口的内容(字)输入到AX
MOV DX,3F8H
IN AL,DX;把3F8H端口的内容(字节)输入到AL
(2)输出指令OUT。
格式:OUT PORT,AL
OUT PORT,AX
OUT DX,AL
OUT DX,AX
功能:把累加器的内容传送给外设端口。
说明:对累加器和端口号的选择限制同IN指令。
【例2-24】
OUT 6lH,AL;把AL寄存器的内容输出到6lH端口
OUT 20H,AX;把AX内容输出到20H端口
MOV DX,3F8H
OUT DX,AL;把AL寄存器的内容输出到3F8H端口
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。