第三章80x86指令系统Word文档下载推荐.docx
《第三章80x86指令系统Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《第三章80x86指令系统Word文档下载推荐.docx(43页珍藏版)》请在冰豆网上搜索。
(SP)←(SP)–2((SP)+1,(SP))←(SRC)
32位指令:
(ESP)←(ESP)–4((ESP)+3,(ESP)+2,(ESP)+1,(ESP))←(SRC)
PUSH指令格式可以有四种格式:
PUSHreg
PUSHmem
PUSHdata
PUSHsegreg
也就是说,它可使用所有的寻址方式,但8086不允许PUSH指令使用立即数寻址方式,只有286及其后继机型允许使用立即数寻址。
②POP指令格式:
POPDST
(DST)←((SP)+1,(SP))(SP)←(SP)+2
(DST)←((ESP)+3,(ESP)+2,(ESP)+1,(ESP))(ESP)←(ESP)+4
POP指令允许的格式有:
POPreg
POPmem
POPsegreg
即POP指令不允许使用立即数寻址方式。
还应该说明的是,POP指令的目的为段寄存器时,不允许使用CS寄存器。
以上两条是堆栈的进栈和出栈指令。
堆栈是以“后进先出”方式工作的一个存储区,它必须存在于堆栈段中,因而此段地址存放于SS寄存器中。
它只有一个出入口,所以只有一个堆栈指针寄存器。
当堆栈地址长度为16位时用SP寄存器,堆栈地址长度为32位时用ESP,SP或ESP的内容在任何时候都指向当前的栈顶,所以PUSH和POP指令都必须根据当前SP或ESP的内容来确定进栈或是出栈的存储单元,而且必须及时修改指针,以保证SP或ESP指向当前的栈顶。
堆栈的存取在16位指令中必须以字为单位(不允许字节堆栈),在32位指令中必须以双字为单位,所以PUSH和POP指令只能作字或双字操作。
PUSH和POP指令在操作数长度为16位时,SP或ESP均为±
2,进栈或出栈的是字;
而操作数长度为32位时,SP或ESP均为±
4,进栈或出栈的是双字。
也就是说,地址长度为16位时,使用SP作为堆栈指针,进出栈的可以是字,也可以是双字;
同样,地址长度为32位时,使用ESP作为堆栈指针,进出栈的可以是双字,也可以是字。
要说明的特殊情况是:
8086中的PUSHSP指令入栈的是该指令已修改了的SP新值,而PUSHESP指令入栈的却是ESP在执行该指令之前的旧值。
此外,PUSH和POP指令在使用与存储器有关的寻址方式且用ESP作为基址寄存器时,PUSH指令使用该指令执行前的ESP内容,POP指令则使用该指令执行后的ESP内容来计算基地址。
PUSH和POP指令均不影响标志位。
(5)PUSHA/PUSHAD—所有寄存器出栈指令
①PUSHA指令格式:
PUSHA;
16位通用寄存器依次进栈,进栈次序为:
AX、CX、DX、BX,指令执行前的SP、BP、SI、DI。
指令执行后(SP)←(SP)–16仍指向栈顶。
②PUSHAD指令格式:
PUSHAD;
32位通用寄存器依次进栈,进栈次序为:
EAX、ECX、EDX、EBX,指令执行前的ESP、EBP、ESI、EDI。
指令执行后(SP)←(SP)–32仍指向栈顶。
(6)POPA/POPAD—所有寄存器出栈指令
①POPA指令格式:
POPA;
16位通用寄存器依次出栈,出栈次序为:
DI、SI、BP、SP、BX、DX、CX、AX。
指令执行后(SP)←(SP)+16仍指向栈顶。
应该说明的是:
SP的出栈只是修改了指针使其后的BX能顺利出栈,而堆栈中原先由PUSHA指令存入的SP的原始内容被丢弃,并未真正送到SP寄存器中去。
②POPAD指令格式:
POPAD;
32位通用寄存器依次出栈,出栈次序为:
EDI、ESI、EBP、ESP、EBX、EDX、ECX、EAX。
指令执行后(SP)←(SP)+32仍指向栈顶。
与POPA相同,堆栈中存放的原ESP的内容被丢弃而不装入ESP寄存器。
说明:
a.PUSHA和POPA可用于286及其后继机型。
PUSHAD和POPAD可用于386及其后继机型。
b.堆栈在计算机工作中起着重要的作用,如果在程序中要用到某些寄存器,如果在程序中要用到某些寄存器,但是它的内容在将来工作中还有用,这时就可以用PUSHA/PUSHAD把它们保存在堆栈中,然后在需要时再用POPA/POPAD指令恢复其原始内容。
c.以上指令均不影响标志位。
(7)XCHG—交换指令
XCHG指令格式:
XCHGOPR1,OPR2;
(OPR1)←→(OPR2)
其中OPR表示操作数。
该指令的两个操作数中必须有一个在寄存器中,因此它可以在寄存器之间或者在寄存器与存储器之间交换信息,但不允许使用段寄存器。
指令允许字或字节操作,386及其后继机型还允许双字操作。
该指令可用除立即数外的任何寻址方式,且不影响标志位。
2、累加器专用传送指令
(1)IN长格式为:
INAL,PORT(字节);
(AL)←(PORT)(字节)
INAX,PORT(字);
(AX)←(PORT+1,PORT)(字)
INEAX,PORT(双字);
(EAX)←(PORT+3,PORT+2,PORT+1,PORT)(双字)
短格式为:
INAL,DX(字节);
(AL)←((DX))(字节)
INAX,DX(字);
(AX)←((DX)+1,(DX))(字)
INEAX,DX(双字);
(EAX)←((DX)+3,(DX)+2,(DX)+1,(DX))(双字)
(2)OUT长格式为:
OUTPORT,AL(字节);
(PORT)←(AL)(字节)
OUTPORT,AX(字);
(PORT+1,PORT)←(AX)(字)
OUTPORT,EAX(双字);
(PORT+3,PORT+2,PORT+1,PORT)←(EAX)(双字)
OUTDX,AL(字节);
((DX))←(AL)(字节)
OUTDX,AX(字);
((DX)+1,(DX)←(AX)(字)
OUTDX,EAX(双字);
((DX)+3,(DX)+2,(DX)+1,(DX)←(EAX)(双字)
①所有的I/O端口与与CPU之间的通信都由IN和OUT指令来完成。
其中IN完成从I/O到CPU之间的信息传送,而OUT则完成从CPU到I/O的信息传送。
CPU只能用累加器(AL或AX或EAX)进行接收或发送信息。
外部设备最多可以有65536个I/O端口,端口号(即外部设备的端口地址)为0000H~FFFFH。
其中前256个端口(0~FFH)可用直接在指令中指定。
所以用长格式时可以在指令中直接指定端口号,但只限于外设的前256个端口。
当端口号≥256时,只能使用短格式,此时必须先把端口号放到DX寄存器中(端口号可以从0000~0FFFFH),然后再用IN或OUT指令来传送信息。
②IN和OUT指令提供了双字、字和字节三种使用方式,选用哪一种,则取决于外设端口宽度。
如端口宽度只有8位,则只用字节指令传送信息。
③以上指令均不影响标志位。
必须注意:
这里的端口号或DX的内容均为地址,而传送的是端口中的信息,而且在用短格式时DX内容就是端口号本身,不需要由任何段寄存器来修改它的值。
(3)XLAT—指令格式:
XLATOPR;
16位指令:
(AL)←((BX)+(AL))
(AL)←((EBX)+(AL))
或XLAT;
上式的简写,OPR为阅读程序用的表格首地址。
说明:
①经常需要把将一种代码转换为另一种代码。
例如,把字符扫描码转换成ASCII码,或者把数字0~9转换成7段数码管所需要的相应代码等,XLAT就是为这种用途所设置的指令。
在使用这条指令之前,应该先建立一个字节表格,表格的首地址提前存入BX或EBX寄存器,需要转换的代码应该是相对于表格首地址的位移量也提前存放在AL寄存器中,表格的内容则是所要换取的代码。
该指令可以使用XLAT或XLATOPR两种格式中的任一种,使用XLATOPR时,OPR为表格的首地址(一般为符号地址),但在这里的OPR只是为提高程序的可读性而设置的,指令执行时只使用预先已存入BX或EBX中的表格首地址中的表格首地址,的可读性而设置的,指令执行时只使用预先已存入中的表格首地址,而并不用汇编格式中指定的值。
②该指令不影响标志位。
③必须注意:
由于AL寄存器只用8位,所以表格长度不能超过256。
3、地址传送指令
(1)LEA—有效地址(EA)送寄存器指令
指令格式:
LEAREG,SRC;
(REG)←SRC
①指令把源操作数的有效地址送到指定的寄存器中。
该指令的目的操作数可使用16位或32位寄存器(REG)中,但不能是段寄存器。
源操作数可使用除立即数和寄存器外的任一种存储器寻址方式。
②.LEA指令不影响标志位。
例3.40LEABX,[BX+SI+0F62H]
如指令执行前:
(BX)=0400H,(SI)=003CH
则指令执行后:
(BX)=(BX)+(SI)+0F62H=0400+003C+0F62=139EH
必须注意:
在这里BX寄存器得到的是有效地址而不是该存储单元内容。
如果是MOVBX,[BX+SI+0F62H],则BX中得到是偏移地址为139E单元内容而不是其偏移地址。
例3.41LEABX,LIST
MOVBX,OFFSETLIST
可以看出,这两条指令在功能上是相同的,BX寄存器中都可得到符合地址LIST的值,而且此时MOV指令的执行速度会比LEA指令更快。
但是OFFSET只能与简单的符号地址相连,而不能和诸如LIST[SI]或[SI]等复杂操作数相连。
因此,LEA指令在取得访问变量的工具方面是很有用的。
(2)LDS、LES、LFS、LGS、LSS—指针送寄存器和段寄存器指令
格式以LDS为例为:
LDSREG,SRC;
(REG)←(SRC),(DS)←(SRC+2)或(DS)←(SRC+4)
①该组指令的源操作数只能用存储器寻址方式,根据任一种存储器寻址方式找到一个存储单元。
当指令指定的寄存器是16位寄存器时,把该存储单元中存放的16位偏移地址(即(SRC))装入该寄存器中,然后把(SRC+2)中的16位数装入指令指定的段寄存器中;
当指令指定的是32位寄存器时,把该存储单元中存放的32位偏移地址装入该寄存器中,然后把(SRC+4)中的16位数装入到指定的段寄存器中
②本组指令的目的寄存器不允许使用段寄存器,LFS、LGS和LSS只能用于386及其后继机型中。
③该组指令不影响标志位。
4、标志寄存器传送指令
(1)LAHF—标志送AH指令
LAHF;
(AH)←(FLAGS的低位字节)
(2)SAHF—AH送标志寄存器指令
SAHF;
(FLAGS的低位字节)←(AH)
(3)PUSHF/PUSHFD—标志进栈指令
PUSHF;
(SP)←(SP)-2
((SP)+1,(SP))←(FLAGS)
PUSHFD;
(ESP)←(ESP)-4
((ESP)+3,(ESP)+2,(ESP)+1,(ESP))←(EFLAGSAND0FCFFFFH)(清除VM和RF位)
(4)POPF/POPFD—标志出栈指令
POPF;
(FLAGS)←((SP)+1,(SP))
(SP)←(SP)+2
POPFD;
(EFLAGS)←((ESP)+3,(ESP)+2,(ESP)+1,(ESP)),
(ESP)←(ESP)-4
这组指令中LAHF、PUSHF/PUSHFD不影响标志位。
SAHF和POPF/POPFD则由装入的值来确定标志位的值。
但POPFD指令不影响VM,RF,IOPL,VIF和VIP的值。
5、类型转换指令
(1)CBW—字节转换为字指令
CBW
执行操作:
AL的内容符号扩展到AH,形成AX中的字。
即如果(AL)的最高有效位为0,则(AH)=0;
如(AL)的最高有效位为1,则(AH)=0FFH。
(2)CWD/CWDE—字转换为双字指令
CWD
AX的内容符号扩展到DX,形成DX:
AX中的双字。
即如果(AX)的最高有效位为0,则(DX)=0;
如(AX)的最高有效位为1,则(DX)=0FFFFH。
CWDE
AX的内容符号扩展到EAX,形成EAX中的双字。
(3)CDQ—双字转换为4字指令
CDQ
EAX的内容符号扩展到EDX,形成EDX:
EAX中的4字。
(4)BSWAP—字节交换指令
BSWAPreg32
该指令只能用于486及其后继机型。
reg32指32位寄存器。
使指令指定的32位寄存器的字节次序变反。
具体操作为:
1、4字节互换,2、3字节互换。
二、算术指令
80x86的算术运算指令包括二进制运算及十进制运算指令。
算术指令用来执行算术运算,它们中有双操作数指令,也有单操作数指令。
双操作数指令的两个操作数中除源操作数为立即数的情况外,必须有一个操作数在寄存器中。
单操作数指令不允许使用立即数寻址方式。
1、加法指令
(1)ADD—加法指令
ADDDST,SRC;
(DST)←(DST)+(SRC)
(2)ADC—带进位加法指令
ADCDST,SRC;
(DST)←(DST)+(SRC)+CF(CF为进位位的值)
(3)INC—加1指令
INCOPR;
(OPR)←(OPR)+1
以上三条指令都可作字节或字运算,386及后继机型还可作双字操作,而且除INC指令不影响CF标志外,它们都影响条件标志位。
(4)XADD—交换并相加指令
XADDDST,SRC;
TEMP←(DST)+(SRC),(SRC)←(DST),(DST)←TEMP
该指令只能用于436及其后继机型,它把目的操作数装入源操作数,并把源和目的操作数之和送目的地址。
该指令的源操作数只能用寄存器寻址方式,目的操作数则可用寄存器或任一种存储器寻址方式。
指令可作双字、字或字节适算。
它对标志位的影响和ADD指令相同。
条件标志(或称条件码)位中最主要的是CF,ZF,SF,OF四位,分别表示了进位、结果为零,符号和溢出的情况。
执行加法指令的时候,CF位是根据最高有效位是否向最高位的进位来设置的。
有进位的时候CF=1,无进位的时候CF=0。
OF位则根据操作数的符号及其变化情况来设置的:
若两个操作数的符号相同,而结果的符号与之相反时OF=1,否则OF=0。
溢出位OF既然是根据数的符号及其变化来设置的,当然它是用来表示带符号数的溢出的,从其设置条件来看结论也是明显的。
CF位可以用来表示无符号数的溢出。
一方面,由于无符号数的最高有效位只有数值意义而无符号意义,所以该位产生的进位应该是结果的实际的进位值,但是在有限数位的范围内就说明了结果的溢出情况;
另一方面,它所保存的进位值有时候还是有用的。
8位二进制数可以表示十进制数的范围是:
无符号数为0~255,带符号数为-128~+127。
16位二进制数可以表示十进制数的范围是:
无符号数为0~65535,带符号数为-32768~+32767。
ADC及INC对条件码的设置方法与ADD指令相同,但INC指令不影响CF位标志。
例3.46下列指令序列可在8086和80286中实现两个双精度数的加法。
设目的操作数存放在DX和AX寄存器中,其中DX存放高位字。
源操作数存放在BX、CX中,其中BX存放高位字。
指令执行前:
(DX)=0002H,(AX)=0F365H,(BX)=0005H,(CX)=0E024H
指令序列为ADDAX,CX
ADCDX,BX
则第一条指令执行后(AX)=0D389H,SF=1,ZF=0,CF=1,OF=0
第二条指令执行后(DX)=0008H,SF=0,ZF=0,CF=0,OF=0
因此该指令序列执行完后(DX)=0008H,(AX)=0D389H结果正确。
可以看出,为实现双精度加法,必须用两条指令分别完成低位字和高位字的加法,而且在高位字相加时,应该使用ADC指令,以便把前一条ADD指令作低位字加法所产生的进位值加入高位字之内。
另外,带符号的双精度数的溢出,应该根据ADC指令的OF位来判断,而作低位加法用的ADD指令的溢出是无意义的。
在80386及其后继机型中,因机器字长为32位,故可直接用双字指令实现32位字的相加。
如ADDEAX,ECX不必再用上述两条指令的指令序列来实现,但它可以用同样的方法来实现64位字的相加。
2、减法指令
(1)SUB—减法指令
SUBDST,SRC;
(DST)←(DST)-(SRC)
(2)SBB—带借位减法指令
SBBDST,SRC;
(DST)←(DST)-(SRC)-CF
(3)DEC—减1指令
DECOPR;
(OPR)←(OPR)-1
(4)NEG—求补指令
NEGOPR;
(OPR)←-(OPR)
亦即把操作数按位求反后末位加1,因而执行的操作也可表示为:
(OPR)←0FFFFH-(OPR)+1
(5)CMP—比较指令
CMPOPR1,OPR2;
(OPR1)-(OPR2)
该指令与SUB指令一样执行减法操作,但它并不保存结果,只是根据结果设置条件标志位。
CMP指令后往往跟着一条条件转移指令,根据比较结果产生不同的程序分支。
(6)CMPXCHG—比较并交换指令
CMPXCHGDST,SRC;
源操作数(SRC)只能用8位、16位或32位寄存器寻址,目的操作数(DST)则可用寄存器或任一种存储器寻址方式。
执行的操作:
累加器AC与DST相比较,如(AC)=(DST),则ZF←1,(DST)←(SRC);
否则ZF←0,(AC)←(DST)
累加器可为AL、AX或EAX寄存器。
该指令对其他标志的影响与CMP指令相同。
(7)CMPXCHG8B—比较并交换8字节指令
该指令只能用于Pentium及其后继机型。
源操作数为存放于EDX,EAX中的64位字,目的操作数可用存储器寻址方式确定一个64位字。
该指令只影响ZF标志。
CMPXCHG8BDST
执行操作:
EDX,EAX与DST比较,若(EDX,EAX)=(DST),则ZF←1,(DST)←(ECX,EBX);
否则ZF←0,(EDX,EAX)←(DST)
以上前六种指令均可均可作字或字节运算,386及其后继机型还可作双字运算,而且除DEC不影响CF标志外,它们都影响条件标志位。
减法运算的条件码情况和加法类似。
CF位说明无符号数相减的溢出,同时它又确实是被减数的最高有效位向高位的借位值。
OF位则说明带符号数的溢出。
减法的CF值反映了无符号数运算中的借位情况,因此当作为无符号数运算时,若减数>
被减数,此时有借位,则CF=1;
否则CF=0。
或者,也可以简单地用二进制减法运算中最高有效位向高位的进位的情况来判别:
有进位的时候CF=0,无进位的时候CF=1。
减法的OF位的设置方法为:
若两个数的符号相反,而结果的符号与减数相同,则OF=1;
除上述情况外OF=0。
OF=1说明带符号数的减法溢出,结果是错误的。
NEG指令的条件码设置情况:
NEG指令的条件码按照求补后的结果设置,只有当操作数为0的时候,求补运算的结果使得CF=0,其他情况都为CF=1。
所以,只有当字运算时对-128求补,以及字运算时对-32768求补和双字运算的时候对-2^31求补的情况下OF=1,其他则均为OF=0。
3、乘法指令
(1)MUL指令格式:
MULSRC;
字节操作:
(AX)←(AL)×
(SRC)
字操作:
(DX,AX)←(AX)×
双字操作:
(EDX,EAX)←(EAX)×
(2)IMUL①指令格式:
IMULSRC;
与MUL相同,但必须是带符号数,而MUL是无符号数
说明:
a.在乘法指令中目的操作数必须是累加器,字节运算为AL,字运算为AX,双字运算为EAX,指令中源操作数可以使用除立即数方式以外的任何一种寻址方式。
b.乘法指令对除CF和OF以外的条件码无定义。
(无定义是指该标志位不确定)
c.MUL指令和IMUL指令的使用条件是由数的格式决定的。
很明显(11111111b)*(11111111b)当把它看作无符号数时应为255d×
255d=65025d,而把它看作带符号数时则为(-1)×
(-1)=1。
因此必须根据所要相乘数的格式来决定选用哪一种指令。
d.对于MUL指令,如果乘积的高一半为0,即字节操作的(AH)或字操作的(DX)或双字操作的(EDX)为0,则CF和OF均为0;
否则(即字节操作的(AH)或字操作的(DX)或双字操作的(EDX)非0),则CF和OF均为1。
这样的条件码设置可以用来检查字节相乘的结果是字节还是字,或者可以检查字相乘的结果是字还是双字,或者可以检查双字相乘的结果是双字还是4字。
对于IMUL指令,如果乘积的高一半是低一半的符号扩展则CF和OF均为0,否则就均为1。
②对于80286及其后继机型,IMUL出上述的单操作数指令(累加器是隐含的)外,还增加了双操作数和三操作数指令格式。
指令格式一:
IMULREG,SRC;
(REG16)←(REG16)×
双字操作:
(REG32)←(REG32)×
a.目的