一、数据传送指令
1. 通用数据传送指令
通用表示符号
data:立即数
DST:目的操作数
SRC:源操作数
reg:寄存器
segreg:段寄存器
mem:存储器
ac:累加器
MOV 传送指令
格式:MOV DST,SRC
效果:(DST)←(SRC)
- 一张图解释MOV指令移动方向
PUSH,POP 进栈出栈指令
格式:PUSH DST
效果:(SP)←(SP)-2
((SP)+1,(SP))←(SRC)
格式:POP DST
效果:(DST)←((SP)+1,(SP))
(SP)←(SP)+2
- 堆栈段中地址是从高地址往低地址生长的,所以进栈时SP要-2,出栈时SP要+2
- 操作的是堆栈段,指针是SP
- 存取必须以字为单位
- PUSH和POP不影响标志位
PUSHA 所有寄存器进栈指令
POPA 所有寄存器出栈指令
格式:PUSHA
效果:将当前AX,CX,DX,BX,SP,BP,SI,DI依次入栈
(SP)←(SP)-16
格式:POPA
效果:寄存器DI,SI,BP,SP,BX,DX,CX,AX依次出栈
(SP)←(SP)+16
- 为了让SP后面的内容顺利出栈,栈中对应SP的内容并没有真正送入SP寄存器中去
- 这两条指令可以保存当前寄存器的状态,之后要用的时候可以用POPA来恢复
XCHG 交换指令
格式:XCHG OPR1,OPR2
效果:(OPR1)↔(OPR2)
- 必须有一个是在寄存器中
- 不能用段寄存器
2. 累加器专用传送指令
IN OUT 输入输出指令
长格式:IN AL,PORT 效果:(AL)←(PORT)
长格式:IN AX,PORT 效果:(AL)←(PORT+1,PORT)
短格式:IN AL,DX 效果:(AL)←((DX))
短格式:IN AX,DX 效果:(AX)←((DX+1),(DX))
长格式:OUT PORT,AL 效果:(PORT)←(AL)
长格式:OUT PORT,AX 效果:(PORT+1,PORT)←(AX)
短格式:OUT DX,AL 效果:((DX))←(AL)
短格式:OUT DX,AX 效果:((DX+1),(DX))←(AX)
- 短格式和长格式:前256个端口(0~FFH)可以直接在指令中指定,当端口号≥256时,只能使用短格式,必须先把端口号放到DX中,然后再操作
- 含有AL的指令是传字节,含有AX的是传字,具体使用哪一种取决于外设端口宽度
XLAT 换码指令
格式:XLAT OPR或
XLAT
效果:(AL)←((BX)+(AL))
- 顾名思义,它能将一种代码转换为另一种代码,要预先建立一个表格,在转换之前,将表格的首地址存入BX,这样根据不同的AL值就能找到对应的值
- OPR是表格的首地址(一般为符号地址),用于提高程序可读性,程序执行时还是按照BX来找首地址的,所以不加也没关系
3. 地址传送指令
LEA 有效地址送寄存器指令
格式:LEA REG,SRC
效果:(REG)←SRC
- 将源操作数的有效地址传送到指定的寄存器中,注意这里加不加括号的区别
- 目的操作数为16位寄存器,但是不能使用段寄存器
- 该指令不影响标志位
LDS LES 指针送寄存器和段寄存器指令
格式:LDS REG,SRC
效果:(REG)←(SRC)
(SREG)←(SRC+2)
- 在存储单元中找到16位偏移地址SRC的位置后,把第一个字存入REG,第二个字存入DS
- 不影响标志位
- LES和LDS类似,只是把DS换成了ES
LAHF SAHF标志寄存器传送指令
首先,请熟悉一下这最复杂的寄存器FLAGS吧,这里每一位都代表了不同的含义,用来标志状态。
好了,预热完后,我们开始
格式:LAHF
效果:(AH)←(FLAGS低字节)
- 将FLAGS寄存器的低八位放到AH寄存器中,那到底是哪八位呢?这里的FLAG八位分别是这样安排的(顺序从大到小):
FLAGS= [SF] [ZF] [0] [AF] [0] [PF] [1] [CF](二进制八位)
7:SF
6:ZF
5:0
4:AF
3:0
2:PF
1:1
0:CF
可以看到,这里的1,3,5的值都已经定好了,无法修改 - 忘了什么是AH?想想AX的组成,AH高八位,AL第八位
格式:SAHF
效果:(FLAGS低字节)←(AH)
- 和上面LAHF差不多,将AH传入FLAGS的低字节,其中第1,3,5位都是定好的改不了的
- 要是还看不懂往上翻
PUSHF 标志进栈指令
格式:PUSHF
效果:(SP)←(SP)-2
((SP+1),(SP))←(FLAGS)
- 将FLAGS寄存器的十六位传入指定的堆栈段中,由于要传入堆栈段,所以SP指针要提前-2空出16位的空间
格式:POPF
效果:((SP+1),(SP))
(SP)←(SP)+2
- 从堆栈段传一个字到FLAGS寄存器,由于堆栈段数据传出,传送到FLAGS之后要将SP+2减少16位的空间
5. 类型转换指令
格式:CBW
效果:将AL扩展到AH。如果AL最高有效位为0,则AH=0;如果AL最高有效位为1,则AH=0FFH
- 在运算的时候,如果两个数的位数不一样的话,就要进行类型转换,以确保运算的正确性,比如八位的-1是AL=0FFH,当它与16位数运算时,如果不扩展位数,那么就是AX=00FFH,显然会出问题,扩展了之后,AX=0FFFFH,就保证结果正确了
格式:CWD
效果:将AX扩展到DX,形成DX:AX中的双字。如果AX最高有效位为0,则DX=0;如果AX最高有效位为1,则DX=0FFFFH
二、算术指令
1. 加法指令
ADD 加法指令
格式:ADD DST,SRC
效果:(DST)←(DST)+(SRC)
- 效果和高级语言中的赋值语句差不多,不过要注意运算位数和溢出情况
- 影响条件标志位
ADC 带进位加法指令
格式:ADC DST,SRC
效果:(DST)←(DST)+(SRC) +CF
- 把CF的值也加了进去,这样就能实现大数加减,先用ADD把低位和低位相加,然后进位自然到了CF中,再用ADC把高位、高位和标志位相加
- 影响条件标志位
INC 加一指令
格式:INC OPR
效果:(OPR)←(OPR)+1
- 影响条件标志位(除CF以外)
XADD 交换并相加指令
格式:XADD DST,SRC
效果:TEMP=(SRC)+(DST)
(SRC)←(DST)
(DST)←TEMP
2. 减法指令
SUB 减法指令
格式:SUB DST,SRC
效果:(DST)←(DST)-(SRC)
- CF=1:减数>被减数;否则为0
- OF=1:两数符号相反,结果符号与减数相同;否则为0
SBB 带借位减法指令
格式:SBB DST,SRC
效果:(DST)←(DST)-(SRC)-CF
- CF=1:减数>被减数;否则为0
- OF=1:两数符号相反,结果符号与减数相同;否则为0
DEC 减一指令
格式:DEC OPR
效果:(OPR)←(OPR)-1
NEG 求补指令
格式:NEG OPR
效果:(OPR)←0FFFFH-(OPR)+1
- 条件码按求补后的结果设置
- CF=0:操作数为0时
CMP 比较指令
格式:CMP OPR1,OPR2
效果:(OPR1)-(OPR2)
- 以上减法指令除DEC不影响CF标志以外,其它都影响条件标志位
3. 乘法指令
MUL 无符号数乘法
IMUL 带符号数乘法
格式:MUL SRC
格式:IMUL SRC
效果:字节 (AX)←(AL)*(SRC)
字(DX,AX)←(AX)*(SRC)
4. 除法指令
DIV 无符号数除法
IDIV 带符号数除法
格式:DIV SRC
效果:16位数(AL)←(AX)/(SRC)的商
(AH)←(AX)/(SRC)的余数
32位数(AX)←(DX,AX)/(SRC)的商
(DX)←(DX,AX)/(SRC)的余数
三、逻辑指令
1. 逻辑运算指令
AND 逻辑与
格式:AND DST,SRC
效果:(DST)←(DST)∧(SRC)
OR 逻辑或
格式:OR DST,SRC
效果:(DST)←(DST)∨(SRC)
NOT 逻辑非
格式:NOT OPR
效果:(OPR)←(非OPR)
- 不允许使用立即数
XOR 异或
格式:XOR DST,SRC
效果:(DST)←(DST)⊕(SRC)
TEST 测试
格式:TEST OPR1,OPR2
效果:(OPR)∧(OPR2)
- 这条指令结果不保存,会改变条件码
- 源操作数不是立即数:至少有一个操作数必须存放在寄存器中,另一个操作数可以使用任意寻址方式
- NOT不影响操作数
- AND可以将某些位置0,OR将某些位置置1,TEST测试某些位置是否为1,XOR将某些位置取反
2. 移位指令
SHL 逻辑左移
格式:SHL OPR,1/CL
效果:将OPR向左移1位或CL位,如果要移CL位,先把移位次数置于CL中,右边多余的位用0补,溢出位放在CF中
- 根据移位后的结果设置SF,ZF,PF位
SAL 算术左移
和算术左移效果一样
SHR 逻辑右移
格式:SHR OPR,1/CL
效果:将OPR向右移1位或CL位,如果要移CL位,先把移位次数置于CL中,左边多余的位用0补,溢出位放在CF中
- 根据移位后的结果设置SF,ZF,PF位
SAR 算术右移
和算术右移效果一样
ROL 循环左移
格式:ROL OPR,1/CL
效果:向左移1或CL位,溢出位补在右边,同时放在CF中
ROR 循环右移
格式:ROR OPR,1/CL
效果:向右移1或CL位,溢出位补在左边,同时放在CF中
RCL 带进位循环左移
格式:RCL OPR,1/CL
效果:向左移1或CL位,溢出位放在CF中,同时原先的CF值补在右边
RCR 带进位循环右移
格式:RCR OPR,1/CL
效果:向右移1或CL位,溢出位放在CF中,同时原先的CF值补在左边
- 循环指令只能改变CF和OF,移位指令根据结果改变SF,ZF,PF
- OF当移位数为1时有意义,根据移位前后当最高有效位发生变化时为1
-
这张图解释得很清楚
四、串处理指令
1. 可以与REP配合使用的指令
REP 重复串操作
格式:REP 串操作指令(MOVS,STOS,LODS,INS,OUTS)
效果:重复执行串操作指令,每执行一次CX-1,直到CX=0为止
- 也就是说,CX要预先存指令的操作次数
MOVSB 串传送
格式:
MOVS DST,SRC
MOVSB (字节)
MOVSW (字)
效果:
MOVSB:将 DS:[SI] 传一个字节到 ES:[DI] 中。如果DF=0,则SI+1,DI+1;如果DF=1,则SI-1,DI-1
MOVSB:将 DS:[SI] 传一个字到 ES:[DI] 中。如果DF=0,则SI+2,DI+2;如果DF=1,则SI-2,DI-2
- 可以看出,DF是用来控制方向的,所以再介绍两条指令
CLD:令DF=0
STD:令DF=1 - 可以与REP连用,用来复制DS中的字符串到ES中
STOS 传入指令
格式:
STOS DST
STOSB (字节)
STOSW (字)
效果:
STOSB:DS:[DI]←(AL),DF=0时,(DI)←(DI)+1,DF=1时,(DI)←(DI)-1
STOSW:DS:[DI]←(AX),DF=0时,(DI)←(DI)+2,DF=1时,(DI)←(DI)-2
- 与REP连用,将连续的DS区域赋值,可以用来初始化
LODS 从串中取指令
格式:
LODS SRC
LODSB (字节)
LODSW (字)
效果:
LODSB:(AL)←DS:[SI],如果DF=0,(SI)←(SI)+1;如果DF=1,(SI)←(SI)-1
LODSw:(AX)←DS:[SI],如果DF=0,(SI)←(SI)+2;如果DF=1,(SI)←(SI)-2
INS 串输入指令
格式:
INS SRC
INSB (字节)
INSW (字)
效果:把端口号在DX寄存器中的I/O空间的字节、字传送到附加段中的目的变址寄存器所指向的存储单元中。并根据DF修改变址寄存器的内容
- 与REP连用,可以把成组的字节、字从I/O端口输入长度为CX的缓冲区中
OUTS 串输出指令
格式:
OUTS SRC
OUTSB (字节)
OUTSW (字)
效果:把源变址寄存器中所指向的字节、字传送到端口号在DX的寄存器中的I/O端口中去。并根据DF修改变址寄存器的内容
- 与REP连用,可以把成组的字节、字输入长度从存储器中传送到I/O空间
2. 与REPE/REPZ 和 REPNE/REPNZ联合工作的CMPS和SCAS指令
REPE/REPZ 当相等/为零时重复串操作
格式:REPE/REPZ String Primitive
效果:
CX=0或ZF=0(两数不相等时)退出,否则继续执行:CX-1,执行其后的指令,重复以上操作
REPNE/REPNZ 当不相等/不为零时重复串操作
格式:REPNE/RENPZ String Primitive
CMPS 串比较指令
用法:
CMPS SRC,DST
CMPSB (字节)
CMPSW (字)
效果:
指令把源变址寄存器中指向数据段的字节、字与目的地址寄存器所指向的附加段中的一个字节、字相减,不保存结果,会记录条件码
SCAS 串扫描指令
格式:
SCAS DST
SCASB (字节)
SCASW (字)
效果:
指令把AL、AX的内容与目的变址寄存器在附加段中的一个字节、字进行比较,并不保存结果,会记录条件码
控制转移指令
1. 无条件转移指令
JMP 跳转指令
段内直接短转移
格式:JMP SHORT OPR
效果:(IP)←(IP)+8位位移量
- IP是指针寄存器,控制运行的程序位置
- 位移量可以是符号地址
段内直接近转移
格式:JMP NEAR PRT OPR
效果:(IP)←(IP)+16位位移量
段内间接近转移
格式:JMP WORD PRT OPR
效果:(IP)←(EA)
段间直接远转移
格式:JMP FAR PTR ORP
效果:
(IP)←OPR的段内偏移地址
(CS)←OPR的段内偏移地址
段间间接远转移
格式:JMP DWORD PTR OPR
效果:
(IP)←(EA)
(CS)←(EA+2)
2. 条件转移指令
- 所有的条件转移指令不影响条件码
根据单个条件标志的设置情况转移
JZ/JE 结果为零/不相等则转移
格式:JZ/JE OPR
条件:ZF=1
JS 结果为负则转移
格式:JS OPR
条件:SF=1
JNS 结果为正则转移
格式:JNS OPR
条件:SF=0
JO 溢出则转移
格式:JO OPR
条件:OF=1
JNO 不溢出则转移
格式:JNO OPR
条件:OF=0
JP 奇偶位为1则转移
格式:JP/JPE OPR
条件:PF=1
JNP 奇偶位为0则转移
格式:JNP/JPO OPR
条件:PF=0
JB/JNAE/JC 低于/等于/进位为1转移
格式:JB/JNAE/JC OPR
条件:CF=1
JNB/JAE/JNC 高于/等于/进位为0转移
格式:JNB/JAE/JNC OPR
条件:CF=0
比较两个带符号数,并根据比较结果转移
JB 低于/进位位为1则转移
JNB 高于/进位位为0则转移
JBE/JNA 高于则转移
格式:JBE/JNA OPR
条件:CF∨ZF=1
JNBE/JA 低于则转移
格式:JNBE/JA OPR
条件:CF∨ZF=0
JL/JNGE 小于则转移
格式:JL/JNGE OPR
条件:SF⊕OF=1
JNL/JGE 大于或等于则转移
格式:JNL/JGE OPR
条件:SF⊕OF=0
JLE/JNG 小于或等于则转移
格式:JLE/JNG OPR
条件:(SF⊕OF)∨ZF=1
JNLE/JG 大于则转移
格式:JNLE/JG POR
条件:(SF⊕OF)∨ZF=0