[转载]汇编语言笔记之X86指令系统
(2012-05-10 12:59:16)
标签:
转载 |
第三部分 指令系统
3.1 数据传送指令
负责把数据,地址或者寄存器传送到寄存器或者内存单元中;
3.1.1通用数据传送指令
3.1.1.1 mov指令
指令格式:
mov dst, src
比较简单,需要注意的地方是:
mov指令不破坏源操作数的内容
mov指令不允许从存储单元传递到存储单元
源操作数和目的操作数的地址必须相等
立即数不能作为目的操作数
3.1.1.2 movsx和movezx指令
movsx和movzx指令只能出现在386,486和pentium机型的指令集中。
movsx叫做传送即符号扩展指令
movzs叫做传送机零扩展指令
备注:
movsx和movzx指令中的源操作数的长度只能为目的操作数的长度的一半;
符号扩展指令将目的操作指令的高一半全部用与操作数的符号位来填充,源操作数为正,则填充0,否则填充1;
零扩展指令将目的操作数的高一半以0填充,常用于不带符号数。
例如:
movsx cx, bl
设bl=1101 0111B,则执行指令后cx=1111 1111 1101 0111B
若bl=0101 0111B,则执行指令后cx=0000 0000 0101 0111B
movzx eax, data
设(data)=87adhj,则执行指令后eax=000087adh
3.1.1.3 echg指令
格式:
xchg opr1, opr2
功能:完成opr1和opr2操作数的互换
3.1.1.4 bswap指令
格式:bswap opr
功能:将reg32寄存器的第一和第四字节互换,第二和第三字节互换。
备注:这个指令是80486及以上机型新增指令
3.1.2 堆栈指令
主要用于保护现场
3.1.2.1 push指令
格式:
push src
pusha
pushad
pushf;将16位标志寄存器入栈
pushfd;将32位标志寄存器入栈
功能:将源操作数内容压栈,同时自动修改栈顶指针。
备注:
8086~80286总是将16位数据压栈,386以上的机器可以将32位的数据压栈;
任何段寄存器的内容都可以压栈
pusha指令将16位通用寄存器压栈,压栈顺序依次为:ax, cx ,dx, bx, sp, bp, si, di;
pushad将32位通用寄存器压栈,顺序同pusha;
当压入16位数据时,首先高位字节放在sp-1中;然后低位字节放在sp-2中,接着sp=sp-2;32位数据压栈类似。
3.1.2.2 pop指令
格式:
pop dst
popa
popad
popf
popfd
功能:与push指令相反。
备注:
立即数不能作为pop的操作数
代码段寄存器cs不能作为pop操作数
pop指令执行后,栈顶指针加2或者加4
3.1.3 地址传送指令
主要用来传送操作数的地址,指令有lea, lds, les, lfs, lgs, lss
3.1.3.1 lea指令
格式:
lea reg, src
功能:
指令把源操作数的有效地址送到指定寄存器。src是一个存储单元。
3.1.3.2 lds指令
格式:
lds reg, src
功能:
将src存储单元存放的4B内容送到指定的寄存器和ds寄存器中。
其中:(src)->reg, (src+2)->ds
例如:
lds edi, list;将存储在list单元中的4B送到edi寄存器,将存储在list+4单元中的2B送到ds寄存器中
3.1.3.3 les/lfs/lgs/lss
格式:同lds指令
功能:将存储在src中的地址送reg寄存器和相应的段寄存器。
备注:
lea bx,[di] 和mov bx,[di]的区别:
lea bx,[di]是将di指定的偏移量放入bx中;
而mov bx,[di]是将di寻址的存储单元的内容送至bx中。
lea bx, list和mov bx, list的区别:
虽然两者是相同的功能,但是mov bx, list却是错误的指令,因为offset只能用于象符号list这样的简单的操作数。
注意:lss指令非常实用,经常用于保存旧堆栈去地址,而后建立新的堆栈区地址。
3.1.4 标志传送指令
3.1.4.1 lahf
功能:将标志寄存器的最右8位送至AH寄存器
3.1.4.2 sahf
功能:将ah内容送至标志寄存器的最右8位
3.1.5 输入输出指令
输入指令in和输出指令out实现CPU和I/O端口直接的通信。
3.1.6 其它的数据传送指令
格式:
xlat或者xlat opr
功能:
将al和bx的寄存器之和作为一个新的偏移地址,然后将以bx寄存器内容为基地址,这个新的偏移地址对应的存储单元送至al寄存器。
3.2
算术指令系统
算术运算分为二进制算术运算和十进制算术运算。
二进制算术运算分为带符号位的和不带符号位的,带符号位的,最高位为符号位,不带符号位的,所有位都是有效位。
十进制数用BCD码表示,分为压缩的BCD码和非压缩的BCD码。
算术运算指令根据操作结果的某些特征设置6个标志位,各个指令对标志位的影响不同,但服从以下几种原则:
(1)CF(进位标志)
若加法操作最高位有进位或者减法操作最高位有借位,CF置1,否则为0
(2)AF(辅助进位标志)
若加法操作的低半字节有进位或者减法操作的低半字节有借位,AF置1,否则为0
(3)SF(符号标志)
若算术或者逻辑运算结果为正SF置0,结果为负SF置1
(4)ZF(零标志)
若算术或者逻辑运算结果为零ZF置1,结果非零ZF置0
(5)PF(奇偶标志)
若算术或者逻辑运算结果的低八位含有偶数个1,则PF置1,否则置0
(6)OF(溢出标志)
若两个操作数的符号相同,但是结果的符号却相反,则OF置1,否则置0
3.2.1 加法指令
3.2.1.1 add(加法指令)
格式:
add dst,src
功能:将源操作数和目的操作数作为两个二进制数相加,结果送至目的操作数。
3.2.1.2 adc(带进位加法指令)
格式:
adc dst,src
功能:将源操作数,目的操作数和进位标志CF相加,结果送至目的操作数。
3.2.1.3 INC(加1)指令
格式:
INC OPR
功能:将除段寄存器以外的任何寄存器或者存储单元加1.
备注:INT指令不改变进位标志CF
3.2.1.4 XADD(交换相加)指令
XADD是486/pentium微处理器的指令
格式:
XADD DST,SRC
功能:将源操作数和目的操作数相加,和数送目的操作数,原目的操作数内容送源操作数。
例如:
XADD BL,DL
设相加前:
BL=12,DL=2,则相加后BL=14,DL=12
3.2.2 减法指令
3.2.2.1 SUB(减法)指令
格式:
SUB DST, SRC
功能:DST-SRC->DST
3.2.2.2 SBB(带借位的减法)指令
SBB DST, SRC
功能:DST-SRC-CF->DST
3.2.2.3 DEC(减一)指令
功能:和加法相反
3.2.2.4 NEG(求补指令)
功能:和加法相反
3.2.2.5 CMP(比较)指令
格式:
CMP DST,SRC
功能:
用目的操作数减去源操作数,但不讲结构送至目的操作数,只是根据结果设置标志位。
3.2.2.6 CMPXCHG(比较交换)指令
格式:
CMPXCHG DST,SRC
功能:
将目的操作数和累加器内容相比较,若相等,则将源操作数复制到目的操作数,否则源操作数送至累加器
备注:
可用于8,16,32位操作数
3.2.2.7 CMPXCHG8B(8字节比较交换)指令
格式:
CMPXCHG8B OPRD
功能:
将EDX:EAX内的64位值与存储器操作数OPRD比较,若相等,则把ECX:EBX内的64位值送至存储器操作数OPRD;若不相等,则把OPRD内的64位值送至EDX:EAX中。
3.2.3 乘法指令
乘法指令允许字节,字或双字相乘,分为无符号相乘和带符号相乘。
3.2.3.1 MUL(无符号相乘)
格式:
MUL SRC
功能:将累加器(EAX,AX或者AL)中目标操作数与源操作数做无符号相乘。对于字节乘法,被乘数在AL中, 乘积在AX中;对于字乘法,被乘数在AX,乘积放在DX-AX中。
备注:
32位乘法只适用于386以上的机器中,被乘数在EAX中,乘积在EDX-EAX中。
例如:
MUL
MUL
MUL
备注:对于MUL指令,若乘积的高半部分结果为0,则CF和OF置0,否则均为1。
而标志位AF,PF,ZF,SF均没有定义。因此可以根据CF和OF的值来判断运算结果的宽度。
3.2.3.2 IMUL(带符号乘法)指令
格式:
MUL SRC
功能:将累加器(EAX,AX或者AL)中的目标操作数与源操作数做带符号相乘。对于字节乘法,被乘数在AL中, 乘积送AX;对于字乘法,被乘数在AX,乘积送DX-AX;双运算时,被乘数放EAX,乘积送EDX-EAX。
备注:
如果乘积的高半部分(字节为AH,字为DX,双字为EDX)是低半部分的符号扩展,则CF和OF均置0,负责置1
例如:
IMUUL
IMUL
IMUL
3.2.4 除法指令
3.2.4.1 DIV(除法)指令
格式:
DIV SRC
功能:
DIB指令将两个无符号位相除,若源操作数为8位(字节除法),则需将目的操作数(16位)预置于累加器AX中,操作后,商留在AL中,余数留在AH中;若源操作数为16位(字除法),则需将目的操作数(32位)的高位字预置于寄存器DX,地位预置于累加器AX中,操作后,商留在AX中,余数留在DX中,非整数的商舍入成整数的商;若源操作数为32位,则目的操作数(64位)的高32位在EDX中,低32位在EAX中,操作后,商留在EAX中,余数送EDX。
备注:
32位除法只适用于386至pentium微处理器,如果商超过目的寄存器的容量,则产生0类中断,商和余数均为不定值。
例如:
DIV CL;AX内容除以CL内容,商在AL中,余数在AH中
DIV CX;DX-AX内容除以CX内容,商在AX中,余数在DX中
DIV DWORD PTR[SI]
;EDX-EAX内容除以以SI寻址的双字(32位)存储单元内容,商送EAX,余数送EDX
3.2.4.2 IDIV(带符号除法)指令
格式:
IDIV SRC
功能:IDIV完成带符号相除,使用方法和DIV指令一样,商的符号按通常的算术发展而定,余数的符号与被除数的符号相同。对于8位除法,被除数送AX;16位除法,被除数送DX-AX;32位除法,被除数送EDX-EAX中;因此要对不带符号位进行零扩展,对于带符号数要进行符号扩展。符号扩展指令为CBW,CWD,CDQ.
备注:执行IDIV指令,所有的标志位都是任意的。
3.2.4.3 CBW(字节扩展成字)指令
格式:
CBW
功能:将(AL)的符号位扩充到AH中,即若(AL)的符号位为0,则(AH)=00H;若(AL)的符号位为1,则(AH)=0FFH。
备注:指令不影响标志位,在执行字节带符号除法前,CBW将目的操作数从一个字节扩展成双字节的被除数。
3.2.4.4 CWD(字转换成双字)指令
格式:
CWD
功能:将(AX)的符号位扩展到DX,若(AX)的符号位为0,则(DX)=0000H,若(AX)符号位为1,则(DX)=FFFFH。
备注:指令不影响标志位,在执行字带符号除法前,CWD将目的操作数从一个字扩展成双字的被除数。
3.2.4.5 CDQ(双字转换成四字)指令
格式:
CDQ
功能:CDQ将(EAX)的符号位扩展到EDX-EAX中,即若(EAX)的符号位为0,则(EDX)=0000 0000H;若(EAX)的符号位为1,则(EDX)=FFFF FFFFH。
备注:指令不影响标志位,在执行双字带符号除法前,CWD将目的操作数从一个四字扩展成双字的被除数。
对于不带符号位的数来说,数字的零扩展可以使用MOVZX指令,也是使用MOV指令将被除数的高半部分直接赋值为0。
例子如下:
将存在在AL中的带符号数-87,除以CL中的带符号数21的指令如下:
CBW;将AL中的带符号数扩展为AX
IDIV CL;AX内容除以CL内容,商在AL中,余数在AH
分析:AL=-87D=10101001B,执行CBW指令后,AX=1111 1111 1010 1001B=-87D,执行IDIV CL指令后,AL=-4D=1111 1100B, AH=-3D=1111 1101B.
3.3 十进制数算术运算指令
8086至pentium微处理器的十进制都是采用BCD码表示的,但是微处理器没有提供专门的BCD码运算指令,它的十进制数运算是通过对BCD码进行二进制运算,然后用十进制数指令进行调整实现的。BCD码可以分为压缩和非压缩两者形式。
对于压缩BCD码没有设置相应的乘除法调整指令,故只能进行十进制数的加减法;而对于非压缩的BCD码,设置了加减乘除四种调整指令,故可以进行十进制数的全部算术运算。
3.3.1.1 DAA(加法的十进制数调整)指令
格式:
DAA
功能:本指令在两个压缩的BCD码相加后使用,隐含AL为目标操作数。
调整规则如下:
若AF标志为1 或者AL寄存器的低4位为16进制数的A~F,则AL寄存器的内容加06H(注意是06H),并将AF置1;
若CF标志为1或者AL的高4位为十六进制数的A~F,则AL寄存器的内容加60H(注意是60H),并将CF置1。
示例如下:
完成压缩的BCD码表示的17+18运算指令:
MOV AL, 17H;压缩的BCD码17=0001 0111B
ADD AL,18H;AL=17+18=0010 1111B(不再是压缩的BCD码格式)
DAA;调整,AL=0010 1111B+06H=0011 0101B=35
3.3.1.2 DAS(减法的十进制数调整指令)
格式:
DAS
功能:本指令在两个压缩的BCD码相减后使用,隐含AL为目标操作数。
调整规则如下:
若AF标志为1 或者AL寄存器的低4位为16进制数的A~F,则AL寄存器的内容减06H(注意是06H),并将AF置1;
若CF标志为1或者AL的高4位为十六进制数的A~F,则AL寄存器的内容减60H(注意是60H),并将CF置1。
3.3.2 非压缩BCD码调整指令
非压缩BCD码调整又称ASCII调整,因此非压缩的BCD码调整的低4位与十进制数的ASCII码低4位相同,同时非压缩的十进制码低四位为有效位。
3.3.2.1 AAA(加法的ASCII码调整)指令
格式:
AAA
功能:本指令在两个压缩的BCD码相加后使用,隐含的目标操作数为AL。其调整规则如下:
(1)若AL寄存器的低4位为0~9之间,且AF标志为0,则转(3);
(2)若AL寄存器的低4位为十六进制数A~F之间,或者AF为1,则AL寄存器的内容加06H,AH寄存器的内容加1,并将AF置1;
(3)清除AL寄存器的高4位
(4)AF标志的值送CF
3.3.2.2 AAS(减法的ASCII码调整)指令
格式:
AAS
功能:本指令在两个压缩的BCD码相减后使用,隐含的目标操作数为AL。其调整规则如下:
(1)若AL寄存器的低4位为0~9之间,且AF标志为0,则转(3);
(2)若AL寄存器的低4位为十六进制数A~F之间,或者AF为1,则AL寄存器的内容减06H,AH寄存器的内容减1,并将AF置1;
(3)清除AL寄存器的高4位
(4)AF标志的值送CF
3.3.2.3 AAM(乘法的ASCII码调整)指令
格式:
AAM
功能:本指令在两个非压缩的BCD码相乘后使用,隐含的源操作数为AL,目标操作数为AX。
其调整方法:
0AH去除AL寄存器中的内容,商存入AH寄存器,余数存入AL寄存器,并根据AL寄存器的内容设置标志为标志位SF, ZF,PF,但OF,CF,AF标志位没有意义。
3.3.2.4 AAD(除法的ASCII码调整)指令
格式:
AAD
功能:本指令将两个非压缩的BCD码调整为二进制数送入AL作为被除数,并根据结果设置SF,ZF和PF标志,OF,CF和AF标志没有意义,即完成:
(AL)<—0AH*(AH)+(AL),(AH)<—0
备注:
非压缩BCD码除法调整与前面运算不同,它是先调整后运算。
例子:
完成非压缩BCD码36除以6的指令
MOV AX ,0306;非压缩BCD码36
MOV BL, 06H;被除数 6
ADD;调整,AL=0010 0100 = 36 = 0AH*(AH)+(AL)
DIV BL
3.4 逻辑运算指令
逻辑运算指令包括逻辑(布尔)运算指令和移位(含环移)指令,由于它们是按位操作的,又称为位操作指令。
3.4.1 逻辑运算指令
逻辑运算指令对操作数按位进行操作,操作数可以是字或者字节,也可以是双字。除NOT指令不影响标志位外,其它逻辑指令都使得CF和OF置零,AF值不确定。并根据一般的规则设置SF,ZF和PF状态。
3.4.1.1 NOT(逻辑非)指令
格式:NOT OPR
3.4.1.2 OR(逻辑或)指令
格式:OR DST,SRC
3.4.1.3 AND(逻辑与)指令
格式:AND DST,SRC
3.4.1.4 XOR(逻辑异或)指令
格式:XOR DST,SRC
3.4.1.5 TEST(测试)指令
格式:TEST DST,SRC
功能:将两个操作数按位进行与操作,但是不保存运算结果,只根据特征设置标志位。
例子1:将1位十进制数的ASCII码转换成十进制数
分析:1位十进制数的ASCII码和1位十进制数的区别在于高四位,十进制ASCII码的高四位为3,十进制数的高四位为0,只要屏蔽要十进制数ASCII码的高四位即可。
MOV AL, 37
AND AD, 0FH;屏蔽AL高四位(AL)=07H
例子2,将一个十进制数转换成相应的ASCII码。
分析:与上题相反,将这个一位十进制数高四位设置为3即可。
MOV AL 09H
OR AL, 30H; 将AL的高四位设置为3,(AL)=39H
例子3:测试AL的第二位是否为1,若是1则调转到NEXT
分析:要测试操作数的某些位是否为1,需先对该操作数求反,然后用TEST指令进行测试
MOV DL,AL;保存AL的内容不会被破坏
NOT DL
TEST DL, 0000 0100B
JE EXIT;结果为0,跳转到EXIT
备注:执行到TEST指令时,AL的第二位若为1,则TEST指令将其置0,所以ZF=0,使得JE指令使其跳转到EXIT。
例子4:判断EAX的内容是否为78963D0FH
XOR EAX 78963D0FH
JE MATCH
3.4.2 位操作指令
为操作指令是386至pentium微处理器的指令,它们可以对一个二进制位进行测试,设置和扫描操作。
位操作可以分为位测试和位扫描,两类指令。
3.4.2.1 位测试指令
BT OPR1, OPR2
功能:测试OPR1由OPR2指定的位,将测试位送至CF中
BTC OPR1, OPR2
功能:测试OPR1由OPR2指定的位,将测试位送至CF中,并将测试位取反
BTR OPR1, OPR2
功能:测试OPR1由OPR2指定的位,将测试位送至CF中,并将测试位清零
BTS OPR1, OPR2
功能:测试OPR1由OPR2指定的位,将测试位送至CF中,并将测试位置1
备注:
位测试指令是386至pentium微处理器指令,只对CF有影响,SF,OF,AF,Pf没有意义。
例:用位测试指令清除CX的位0和位1,置位CX的位9和位10,并且取反CX的位12。
指令序列:
BTS CX, 9;置位9
BTS CX, 10;置位10
BTR CX, 0;清位0
BTR CS, 1;清位1
BTC CX, 12;位12取反
备注:
OPR1可以是16位或者32位寄存器,也可以是16位或32存储单元,OPR2必须是8位立即数或者与OPR1长度相等的通用寄存器。
3.4.2.2 位扫描指令
位扫描指令也是386至pentium微处理器的指令,共有两条:
BSF OPR1, OPR2
功能:从左至右扫描OPR2中第一个含1的位,并将位号送至OPR1
BSR OPR1, OPR2
功能:从右至左扫描OPR2中第一个含1的位,并将位号送至OPR1
备注:
OPR1可以是16位或者32位寄存器,也可以是16位或32存储单元,OPR2必须是8位立即数或者与OPR1长度相等的通用寄存器。
例子:
设AX中存有16位图形信息,要求仅保留可能有的最左或者最右各一位为1的位。
XOR DX, DX; DX清零
BSF CX, AX; 扫描取最左一位为1的位置
JZ SHORT DONE;如果不存在,则跳转至DONE
BTS DX, CX;对DX相应位置1
BSR CX,AX; 扫描取最右一位为1的位置
JZ SHORT DONE; 如果不存在,则跳转至DONE
BTS DX, CX; 对DX相应位置1
DONE: MOV AX, DX;结果放在AX中
3.4.3 移位指令
使得操作数向左或者向右移动若干位,所移动的位数有CNT指定。
当只移动一位时,立即数为1;
当移动多位时,移位格式放在CL寄存器。
注意:
OF位只有当CNT=1时有效,当移位后最高有效位的值发生变化时,OF置1,否则为0;
SF,ZF和PF根据移位后的结构设置;而AF的位不确定。
3.4.3.1 SHL(逻辑左移)
格式:
SHL OPR, CNT
CF<—OPR<—0
3.4.3.2 SAL(算术左移)
格式:
SAL OPR, CNT
CF<—OPR<—0
3.4.3.3 SHF(逻辑右移)
格式:
SHL OPR, CNT
0—>OPR—>CF
3.4.3.4 SAF(算术右移)
格式:
SHL OPR, CNT
最高符号位—>OPR—>CF
备注:最高符号位保持不变,故OF置0
3.4.3.5 ROL 循环左移
格式:
ROL OPR, CNT
CF<—OPR
3.4.3.5 ROR 循环右移
格式:
ROR OPR, CNT
OPR—>CF
|__↑
3.4.3.5 RCL (带进位循环左移)指令
格式:
RCL OPR, CNT
CF<—OPR
|_____↑
3.4.3.5 RCR 带进位循环右移
格式:
RCR OPR, CNT
OPR—>CF
|_____↑
3.4.3.6 SHLD 双精度左移指令
格式:
SHLD OPR1,OPR2, CNT
功能:
把OPR1左移CNT位,空出的位数由OPR2的高CNT位补充,OPR2不变,最后移出的位在CF中,若只是移动一位,并且以后会CF与OPR1高位不一致,则OF置1。
示意图:CF<—OPR1<—OPR2
3.4.3.7 SHRD 双精度右移指令
格式:
SHRD OPR1,OPR2, CNT
功能:
把OPR1右移CNT位,空出的位数由OPR2的低CNT位补充,OPR2不变,最后移出的位在CF中,若只是移动一位,并且以后会CF与OPR1高位不一致,则OF置1。
示意图:OPR2—>OPR2—>OPR1
备注:
OPR1可以是16位或者32位寄存器,也可以是16位或者32位存储单元;OPR2只能是通用寄存器,且长度和OPR2一致;CNT可以是八位寄存器,也可以是CL。
备注:
其它指令集比如条件置位指令,处理器控制指令,以及只能在保护模式下执行的指令,以后如果用到的话,再进一步总结吧。
参考书籍:
《汇编语言程序设计(第三版)》 徐建民,邵艳华著,电子工业出版社