80x86指令系统.docx
《80x86指令系统.docx》由会员分享,可在线阅读,更多相关《80x86指令系统.docx(21页珍藏版)》请在冰豆网上搜索。
80x86指令系统
标志寄存器的条件位:
进位位(CF):
最高位有进位(借位)时置1,否则0;
奇偶位(PF):
操作结果低8位hamming重量为偶则置1,否则0;
辅助进位位(AF):
计算中低4位有进位置1,否则0;
零值位(ZF):
计算结果为零则置1,否则0;
符号位(SF):
计算结果为负则置1,否则0;
溢出位(OF):
计算结果超过补码能表示的范围为1,否则0;不同于CF!
!
方向标志位(DF):
串操作中DF=0用+,DF=1用-;
条件位的显示设置指令:
CF:
CLC置CF=0;STC置CF=1;CMCCF取反。
DF:
CLD置DF=0:
STD置DF=1。
IF:
CLI置IF=0:
STI置IF=1。
特别说明:
所有指令未说明均不影响条件标志位。
1数据传送指令
1.1通用数据传送指令
(1)MOV传送指令。
(2)MOVSX带符号扩展传送,386后可用。
(3)MOVZX带零扩展传送,386后可用。
(4)PUSH进栈指令。
POP出栈指令。
操作数必须以字或双字为单位
(6)PUSHA/PUSHAD所有通用寄存器进栈,进栈顺序是EAX,EBX,ECX,EDX,指令执行前的ESP,EBP,ESI,EDI。
POPA/PUSHAD所有通用寄存器出栈,但是丢弃ESP而不装入当前的ESP中。
说明:
PUSHA和POPA操作16位的寄存器,PUSHAD和POPAD操作32位。
(7)XCHG交换指令。
1.2累加器(EAX)专用传送指令
(1)IN格式:
INEAX,PORT或者INEAX,DX,输入指令。
OUT格式OUTPORT,EAX或者OUTDX,EAX,输出指令。
端口号从0000-FFFFH,其中00-FFH可以直接指定,否则必须放在DX中。
(2)XLAT换码指令。
操作:
AL=((EBX)+(AL))。
1.3地址传送指令
(1)LEA有效地址送寄存器指令。
(2)LDS,LES,LSS,LFS,LGS指针送寄存器和段寄存器指令。
后三个只能在386后可以用。
指令格式LDS:
REG,SRC,把SRC单元中存放的内容连续的放如REG和DS中。
1.4标志寄存器传送指令
(1)LAHF标志送AH指令,把标志寄存器低8位送到AH。
(2)SAHFAH送标志指令,把AH的内容送到标志的底8位。
(3)PUSHF/PUSHFD标志进栈指令,其中PUSH是16位。
PUSHFD32位,进栈前清楚VM和RF位。
(4)POPF/POPFD标志出栈指令。
但是POPFD不影响VM,RF,IOPL,VIF,VIP标志位。
1.5类型转换指令
(1)CBW字节转换成字。
把AL符号扩展到AH形成AX字。
(2)CWD/CWDE字转换成双字。
CWD把AX符号扩展形成DX:
AX双字。
而CWDE把AX符号扩展成EAX。
(3)CDQ双字转换成四字。
把EAX符号扩展成EDX:
EAX四字。
(4)BSWAP字节交换指令。
只能用与486以后。
格式:
BSWAPreg32,使得reg32中的1234字节变成4321字节。
2算术指令
2.1加法指令
(1)ADD加法指令。
(2)ADC带进位加法指令。
(3)INC加1指令。
以上三条指令都影响条件标志位,但INC不影响CF。
(4)XADD交换并相加指令。
486以后可以用,交换操作数的值,并做加法。
2.2减法指令
(1)SUB减法指令。
(2)SBB带借位减法指令。
(3)DEC减1指令。
(4)NEG求补(负)指令。
(5)CMP比较指令。
与SUB一样,但是不存结果。
以上指令都影响条件标志位,但DEC不影响CF。
2.3乘法指令
(1)MUL无符号乘法指令。
格式:
MULSRC,字操作AX=AL*SRC,字节操作DX:
AX=AX*SRC,双字节操作EDX:
EAX=EAX*SRC,SRC可以是除立即数以外的任何一种寻址方式。
(2)IMUL有符号乘法指令。
操作同MUL。
乘法指令对除CF和OF以外的条件标志位无定义。
MUL中如果乘积的高一半为0则CF和OF都设置成0,否则设置成1。
IMUL中如果高一半是低一半的符号扩展则设置成0,否则设置成1。
(3)IMULREG,SRC操作REG=REG*SRC。
IMULREG,SRC,IMM操作REG=SRC*IMM。
根据溢出设置CF和OF。
只有在286以后可用。
2.4除法指令
(1)DIV无符号除法指令。
格式:
DIVSRC。
字节操作AL=AX/SRC,AH=AX%SRC(即AL存商,AH存余数),字操作AX=(DX:
AX)/SRC,DX=(DX:
AX)/SRC,双字操作EAX=(EDX:
EAX)/SRC,EDX=(EDX:
EAX)/SRC。
(2)IDIV有符号乘法指令。
操作同DIV。
除法指令对条件标志位均无定义。
2.5十进制调整指令
压缩的BCD码用4位二进制数表示一个十进制数位,非压缩的BCD码用8位为一组表示一个十进制数位,8位中的低4位表示十进制数位,高4位则没有意义。
所以十进制调整指令分成两组:
1.压缩BCD码调整指令
(1)DAA加法的十进制调整指令。
调整AL到BCD压缩码,指令执行之前必须执行ADD或ADC指令。
调整的方法是:
如果AF=1或者AL的低4位大于9,则AL内容加06H,设置AF=1;如果CF=1或者AL的高4位大于9,则AL内容加60H,设置CF=1。
对OF无定义,但影响其他标志位。
(2)DAS减法的十进制调整指令。
调整AL到BCD压缩码,指令执行之前必须执行SUB或SBB指令。
调整的方法是:
如果AF=1或者AL的低4位大于9,则AL内容减60H,设置AF=1;如果CF=1或者AL的高4位大于9,则AL内容减60H,设置CF=1。
对OF无定义,但影响其他标志位。
2.非压缩BCD玛调整指令
(1)AAA加法的ASCII调整指令。
操作:
把AL调整成非压缩的BCD码,AH=AH+调整产生的进位值,指令执行之前必须执行ADD或ADC指令。
调整方法为:
如果AF=1或者AL的低4位大于9,则AL内容加06H,AH内容加1,设置CF=AF=1,否则设置CF=AF=0;清除AL的高四位。
其余标志位无定义。
(2)AAS减法的ASCII调整指令。
操作:
把AL调整成非压缩的BCD码,AH=AH-调整产生的进位值,指令执行之前必须执行SUB或SBB指令。
调整方法为:
如果AF=1或者AL的低4位大于9,则AL内容减06H,AH内容减1,设置CF=AF=1,否则设置CF=AF=0;清除AL的高四位。
其余标志位无定义。
(3)AAM乘法的ASCII调整指令。
操作:
AX=AL的积调整到非压缩BCD码。
调整的方法是:
把AL除以10,商放在AH中,余数保留在AL中。
根据内容设置SF,ZF和PF,但OF,CF和AF无定义。
3逻辑指令
3.1逻辑运算指令
(1)AND逻辑与指令。
(2)OR逻辑或指令。
(3)NOT逻辑非指令。
(4)XOR逻辑异或指令。
(5)TEST测试指令,和AND一样,但是不保存结果,只影响标志位。
以上指令都设置CF=OF=0,AF无定义,根据结果设置SF,ZF,PF。
3.2位测试并修改指令
本组指令在386以后可用。
本组指令影响CF,其他标志无定义。
(1)BT位测试指令。
格式:
BTDEST,SRC,把DEST的第SRC位送入CF。
(2)BTS位测试并置1指令。
先执行BT,并把DEST的该位置1。
(3)BTR位测试并置0指令。
先执行BT,并把DEST的该位置0。
(4)BTC位测试并取反指令。
先执行BT,并把DEST的该位取反。
3.3位扫描指令
本组指令386以后可用,影响ZF,其他标志无定义。
(1)BSF正向位扫描指令。
格式:
BSFREG,SRC,从SRC的第0位开始向右扫描,如遇到第一个为1的位,则把ZF置0,并把该位的位置送入REG;如果SRC=0,则把ZF置1,REG内容无定义。
(2)BSR反正位扫描指令。
除了扫描的方向相反以外,其他和BSF一样。
3.4移位指令
(1)SHL逻辑左移指令。
(2)SAL算术左移指令。
(3)SHR逻辑右移指令。
(4)SAR算术右移指令。
以上四条指令,在8086中如果移位次数大于1则必须把移位次数放在CL中,其他机型则可以使用立即数或者CL,移位次数从1-31。
(5)ROL循环左移指令。
(6)ROR循环右移指令。
(7)RCL带位循环左移指令。
(8)RCR带位循环右移指令。
以上八条指令,CF位根据各条指令的规定设置,OF位只有移位次数是1时才有效,否则无定义。
如果移位次数是1,移位后最高有效位发生变化则OF=1,否则为0。
移位指令根据结果影响SF,ZF,PF,AF则无定义;循环移位指令则不影响CF,OF以外的其他标志位。
(9)SHLD双精度左移指令。
(10)SHRD双精度右移指令。
以上两条指令386以后可用。
格式:
SHLDDEST,REG,n,左移(DEST:
REG),指令结束后不改变REG的值;格式:
SHRDDEST,REG,n,右移(REG:
DEST),指令结束后不改变REG的值。
n在1到31之间,否则自动去模32。
如果n=0则不影响各标志位。
否则根据结果设置SF,ZF,CF,PF,OF和AF的设置和其他移位指令一样。
4串处理指令
(1)MOVS串传送指令。
(2)CMPS串比较指令。
(3)SCAS串扫描指令。
(4)LODS从串取指令。
(5)STOS存入串指令。
(6)INS串输入指令。
(7)PUTS串输出指令。
与上述指令配合只用的前缀指令有:
(1)REP重复。
(2)REPE/REPZ相等/为零则重复。
(3)REPNE/REPNZ不相等/不为零则重复。
串操作指令是处理放在存储器中的数据串,所有串操作指令都可以处理字节或者字,386以后还可以处理双字。
所有的串操作指令隐含的使用ESI当作源地址寄存器(Source-Index),EDI当作目的地址寄存器(Destination-Index)。
选择是加还是减由方向标志OF决定:
OF=1时用加,OF=0时用减。
4.1与REP相配合的MOVS,STOS,LODS,INS,PUTS指令
(1)REP重复串操作直到记数寄存器(16位为CX,32位为ECX)的值为0。
格式:
REP操作,每执行一次记数寄存器的内容减1,直到0停止。
(2)MOVS串传送指令:
MOVSB(字节),MOVSW(字),MOVSD(双字)。
操作:
①(Source-index)=(Destination-index)。
②Source-index=Source-index±1;destination-index=destination-index±1。
(字操作则±2;双字操作则±4)
(3)STOS存入串指令:
STOSB(字节),STOSW(字),STOSD(双字)。
操作:
①(Destination-index)=(AL)。
②Destination-index=Destination-index±1。
(字操作则±2,使用AX;双字操作则±4,使用EAX)
(4)LODS从串取指令:
LODSB(字节),LODSW(字),LODSD(双字)。
操作:
①(AL)=(source-index)。
②source-index=source-index±1。
(字操作则±2,使用AX;双字操作则±4,使用EAX)
(5)INS串输入指令:
INSB(字节),INSW(字),INSD(双字)。
操作:
①(destination-index)=((DX))。
(DX存放I/O端口)
②destination-index=destination-index±1。
(字操作则±2;双字操作则±4)
(5)PUTS串输出指令:
PUTSB(字节),PUTSW(字),PUTSD(双字)。
操作:
①((DX))=(source-index)。
(DX存放I/O端口)
②source-index=source-index±1。
(字操作则±2;双字操作则±4)
4.2与REPE/REPZ和REPNE/REPNZ联合工作的CMPS和SCAS指令
(1)REPE/REPZ执行方式和REP一样,但ZF=0时则退出。
(2)REPNE/REPNZ执行方式和REP一样,但ZF=1时则退出。
(3)CMPS串比较指令:
CMPSB(字节),CMPSW(字),CMPSD(双字)。
操作:
①(Source-index)-(Destination-index)。
②Source-index=Source-index±1;destination-index=destination-index±1。
(字操作则±2;双字操作则±4)
相减后并不保留结果,只根据结果设置条件码。
386后可用。
(3)SCAS串扫描指令:
SCASB(字节),SCASW(字),SCASD(双字)。
操作:
①(AL)-(Destination-index)。
②destination-index=destination-index±1。
(字操作则±2,使用AX;双字操作则±4,使用EAX)
相减后并不保留结果,只根据结果设置条件码。
386后可用。
5控制转移指令
5.1无条件转移指令
JMP是无条件转移指令,分成两类:
段内转移和段间转移。
段内转移只是修改指令指针EIP(IP)的值,而段间转移还有修改代码段CS的值。
(1)段内直接短转移JMPSHORTOPR
执行的操作是:
EIP=EIP+OPR(8位的带符号位移量)
(2)段内直接近转移JMPNEARPTROPR
执行的操作是:
EIP=EIP+OPR(32位的带符号位移量)
(3)段内间接近转移JMPWORDPTROPR
执行的操作是:
EIP=(EA),即OPR的存储值。
(4)段间直接远转移JMPFARPTROPR
执行的操作是:
EIP=OPR的段内地址偏移量
CS=OPR所在段的段地址
(5)段间见解远转移JMPDWORDPTROPR
执行的操作是:
EIP=(EA)
CS=(EA+4)
5.2条件转移指令
条件转移在8086和80286中只提供短转移格式,386以后还提供了近转移格式,这样就可以访问段内的任何位置。
但是条件转移指令不提供段间远转移格式,如需要可以转换成JMP指令来解决。
1.根据单个标志设置转移情况:
(1)JZ(orJE)结果为零(或相等)则转移
测试条件:
ZF=1
(2)JNZ(orJNE)结果不为零(或不相等)则转移
测试条件:
ZF=0
(3)JS结果为负则转移
测试条件:
SF=1
(4)JNS结果不为负则转移
测试条件:
SF=0
(5)JO溢出则转移
测试条件:
OF=1
(6)JNO不溢出则转移
测试条件:
OF=0
(7)JP(orJPE)奇偶位为1则转移
测试条件:
PF=1
(8)JNP(orJNPE)奇偶位为0则转移
测试条件:
PF=0
(9)JC(orJB,orJNAE)进位,或低于,或不高于或者等于,则转移
测试条件:
CF=1
(10)JNC(orJNB,orJAE)不进位,或不低于,或高于或者等于,则转移
测试条件:
CF=0
2.比较两个无符号数CMPA,B,并根据比较结果转移
(1)JC(orJB,orJNAE)转移条件:
A
(2)JNC(orJNB,orJAE)转移条件:
A>=B
(3)JBE(orJNA)转移条件:
A<=B
测试条件:
CFORZF=1
(4)JNBE(orJA)转移条件:
A>B
测试条件:
CFORZF=0
3.比较两个带符号数CMPA,B,并根据比较结果转移
(1)JL(orJNGE)转移条件:
A
测试条件:
SFXOROF=1
(2)JNL(orJGE)转移条件:
A>=B
测试条件:
SFXOROF=0
(3)JLE(orJNG)转移条件:
A<=B
测试条件:
(SFXOROF)ORZF=1
(3)JNLE(orJG)转移条件:
A>B
测试条件:
(SFXOROF)ORZF=0
4.测试CX或者ECX值为0则转移指令
(1)JCXZCX寄存器内容为0则转移
测试条件:
(CX)=0
(2)JECXZECX寄存器内容为0则转移
测试条件:
(ECX)=0
这一组指令只能提供8位的位移量,即他们只能做短转移
5.条件指令设置
指令格式:
SETccDEST,把对应的条件码cc的值存入DEST,386后可用。
其结果都相对于转移条件。
根据单个标志位把DEST置1:
(1)SETZ(orSETE)测试条件:
ZF=1
(2)SETNZ(orSETNE)测试条件:
ZF=0
(3)SETS测试条件:
SF=1
(4)SETNS测试条件:
SF=0
(5)SETO测试条件:
OF=1
(6)SETNO测试条件:
OF=0
(7)SETP(orSETPE)测试条件:
PF=1
(8)SETNP(orSETPO)测试条件:
PF=0
(9)SETC(orSETB,orSETNAE)测试条件:
CF=1
(10)SETNC(orSETNB,orSETAE)测试条件:
CF=0
比较两个无符号数CMPA,B,并根据比较结果把DEST置1
(1)SETC(orSETB,orSETNAE)测试条件:
A
(2)SETNC(orSETNB,orSETAE)测试条件:
A>=B
(3)SETBE(orSETNA)测试条件:
A<=B
(4)SETNBE(orSETA)测试条件:
A>B
比较两个有符号数CMPA,B,并根据比较结果把DEST置1
(1)SETL(orSETNGE)测试条件:
A
(2)SETNL(orSETGE)测试条件:
A>=B
(3)SETLE(orSETNG)测试条件:
A<=B
(4)SETNLE(orSETG)测试条件:
A>B
5.3循环指令
(1)LOOP测试条件:
ECX(CX)=0
(2)LOOPZ/LOOPE测试条件:
ZF=1且ECX(CX)=0
(3)LOOPNZ/LOOPNE测试条件:
ZF=0且ECX(CX)=0
以上三条指令的执行步骤是:
①ECX(CX)=ECX(CX)–1
②检查是否满足测试条件,如果满足则跳转到标号处,只能是短转移。
5.4子程序
(1)CALLDEST调用程序
段内直接近调用:
PUSH(EIP);EIP=EIP+D32。
段内间接近调用:
PUSH(EIP);EIP=(EA)。
段间直接远调用:
PUSH(CS);PUSH(EIP);
EIP=DEST指定的偏移地址
CS=DEST指定的段地址。
段间间接远调用:
PUSH(CS);PUSH(EIP);IP=(EA);CS=(EA+2)。
上述CALL并没加上NEARPTR和FARPTR等属性操作符,实际中可以根据具体情况加上,使用方法参考JMP。
(2)RET(EXP)返回指令
段内近返回RET:
POPEIP。
段内带立即数近返回RETEXP:
POPEIP;ESP=ESP+EXP。
段间远返回RET:
POPEIP;POPCS。
段间带立即数远返回RETEXP:
POPEIP;POPCS;ESP=ESP+EXP。
5.5中断
当CPU响应中断是,把EIP和CS还有标志寄存器FLAGS保存入栈;中断返回时恢复EIP,CS和FLAGS。
中断入口地址称中断向量,存储器的最低地址区的1024字节称中断向量区,存放着256个类型中断例行程序入口地址。
(1)INTN中断指令。
N的值在0到255之间,若缺省N则隐含类型号为3。
不影响除IF,TF,AC以外的标志位(INTO也如此)。
操作:
PUSH(FLAGS);IF=0;TF=0;AC=0;PUSH(CS);PUSH(IP);IP=N*4;CS=N*4+2。
(2)INTO若溢出则中断指令。
若OF=1调用4号类型的中断。
(3)IRET/IRETD从中断返回指令。
IRET用于16位,IRETD用于32位。
操作(16位):
POPIP;POPCS;POPFLAGS。
6处理机控制与杂项操作指令
(1)NOP无操作指令。
机器码占用一个字节存储单元。
(2)HLT停机指令。
使CPU处于停机状态等待一次外部中断到来,中断过后继续执行下面的程序。
(3)WAIT等待指令。
使CPU处于空转状态等待外部中断发生,中断后继续处于等待状态。
(4)LOCK封锁指令。
该指令是一前缀,和其他指令配合使用,用来维持总线的锁存信息,知道与其联合的指令执行完。
(5)BOUNDREG,MEM界限指令。
检查数组的下标是否在上下界以内;如果是则执行下一指令,否则产生5号中断,中断返回时返回地址仍指向BOUND指令。
REG存放数组下标,MEM存放上下界。
(6)ENTERIMM16,IMM8建立堆栈桢指令。
IMM16指定堆栈桢的大小,IMM8给出过程嵌套层数,范围是0到31。
执行的操作是:
PUSHEBP;EBP=ESP;建立堆栈;EBP=ESP–IMM16。
7伪操作(MASM)
7.11.处理器选择
.8086.286.286P.386.386P.486.486P.586.586P……
7.22.段定义
(1)完整的段定义
segmentnameSEGMENT[align-type][combine-type][use-type][‘class’]
……
segmentnameENDS
此外,还必须用ASSUME指明段和段寄存器的关系:
ASSUMEregistername:
segmentname。
取消指定用ASSUMENOTHING。
ASSUME只是指定,并不把段地址装入相应的段寄存器中,除了代码段其他都必须用MOV命令装入。
①定位类型(align-