# 数据传送指令
# MOV
1 2 3 4
| mov reg/mem, imm mov reg/mem/seg, reg mov reg/seg, mem mov reg/mem, seg
|
注:
- 当 src 是 imm,dest 是 mem 时,二者之一必须用 ptr 指定类型
- cs 不能做目的操作数,ip 既不能做源操作数也不能做目的操作数
- 两个操作数必须类型一致
- 立即数不能送直接寻址的内存单元
1 2 3 4 5
| ;错误 mov word ptr[1000h],32A8h ;修改 mov ax, 21A8h mov [1000h], ax
|
# XCHG
1 2
| xchg reg, reg/mem xchg reg/mem, reg
|
# 堆栈操作指令
栈顶是地址较小的一端
修改 sp 值的操作:
- 子程序调用
CALL
- 子程序返回
RET
- 中断调用
INT
- 中断返回
IRET
# PUSH
1
| push r16/m16/seg ;sp <- sp - 2, ss:[sp] <- r16/m16/seg
|
# POP
1
| pop r16/m16/seg ;r16/m16/seg <- ss:[sp], sp <- sp + 2,
|
# 标志传送指令
# 标志送 AH 指令 LAHF
# AH 送标志指令 SAHF
# 标志进栈指令 PUSHF
1
| pushf ;sp <- sp - 2, ss:[sp] <- flags
|
# 标志出栈指令 POPF
1
| popf ;flags <- ss:[sp], sp <- sp + 2
|
# 地址传送指令
# LEA
1
| lea r16, mem ;r16 <- mem的有效地址
|
# LDS&LES
1 2
| lds r16, mem ;r16 <- mem的有效地址, ds <- mem + 2 les r16, mem ;r16 <- mem的有效地址, es <- mem + 2
|
# 状态标志
进位标志 CF
是针对无符号整数运算设计的,反应无符号数据加减运算是否超出范围,是否需要利用进(借)位反映正确结果。
- N 位无符号数据加减运算结果范围是0∼2N−1
溢出标志 OF
用于表示有符号整数进行加减运算的结果是否超出范围
- 处理器默认采用补码的形式表示有符号整数,N 位补码表达的范围是−2N−1∼+2N−1−1
标志 |
0 |
1 |
CF |
(加减)没有进位或借位 |
(加减)有进位或借位 |
OF |
未超出范围 |
超出范围 |
ZF |
运算结果不是 0 |
运算结果是 0 |
SF |
最高位为 0 |
最高位为 1 |
PF |
最低字节中 "1" 的个数是奇数 |
最低字节中 "1" 的个数是偶数 |
AF |
最低半字节无进位 |
最低半字节有进位 |
- 只有当两个相同符号数相加(含两个不同符号数相减)而运算结果的符号与原数据符号相反时产生溢出
符号值对应表:
标志 |
1 |
0 |
CF |
CY |
NC |
OF |
OV |
NV |
ZF |
ZR |
NZ |
SF |
NG |
PL |
PF |
PE |
PO |
AF |
AC |
NA |
运算指令对标志位的影响:
说明:0: 清零 ✓: 有影响 X: 无影响 -: 不确定 (未定义)
![]()
# 加法指令
# ADD
1 2
| add reg, imm/reg/mem ;reg <- reg + imm/reg/mem add mem, imm/reg ;mem <- mem + imm/reg
|
# ADC
1 2
| adc reg, imm/reg/mem ;reg <- reg + imm/reg/mem + CF adc mem, imm/reg ;mem <- mem + imm/reg + CF
|
# INC
不影响 CF,其他影响与 ADD 一致
1
| inc reg/mem ;reg/mem <- reg/mem + 1
|
# 减法指令
# SUB
1 2
| sub reg, imm/reg/mem ;reg <- reg - imm/reg/mem sub mem, imm/reg ;mem <- mem - imm/reg
|
# SBB
1 2
| sbb reg, imm/reg/mem ;reg <- reg - imm/reg/mem - CF sbb mem, imm/reg ;mem <- mem - imm/reg - CF
|
# DEC
不影响 CF,其他影响与 SUB 一致
1
| dec reg/mem ;reg/mem <- reg/mem - 1
|
# NEG
对标志位的影响和用零做减法的 SUB 指令一样
1 2
| neg reg/mem ;reg/mem <- 0 - reg/mem ;对操作数 取反+1
|
# CMP
对标志位的影响和 sub 指令一样
1 2
| cmp reg, imm/reg/mem ;reg - imm/reg/mem cmp mem, imm/reg ;mem - imm/reg
|
# 乘法指令
如果乘积的高一半(AH/DX)没有有效数值, OF=CF=0
,否则 OF=CF=1
# MUL
1 2 3
| ;无符号 mul r8/m8 ;ax <- al × r8/m8 mul r16/m16 ;dx.ax <- ax × r16/m16
|
# iMUL
1 2 3
| ;有符号 imul r8/m8 ;ax <- al × r8/m8 imul r16/m16;dx.ax <- ax × r16/m16
|
# 除法指令
# DIV
1 2 3 4 5
| ;无符号 div r8/m8 ;al <- ax ÷ r8/m8的商 ;ah <- ax ÷ r8/m8的余数 div r16/m16 ;ax <- dx.ax ÷ r16/m16的商 ;dx <- dx.ax ÷ r16/m16的余数
|
# iDIV
1 2 3 4 5
| ;有符号 余数和被除数符号相同 idiv r8/m8 ;al <- ax ÷ r8/m8的商 ;ah <- ax ÷ r8/m8的余数 idiv r8/m8 ;ax <- dx.ax ÷ r16/m16的商 ;dx <- dx.ax ÷ r16/m16的余数
|
# 符号扩展指令
CBW
将 AL
的最高有效位扩展到 AH
CWD
将 AX
的内容符号扩展形成 DX
# 逻辑运算指令
# AND/OR/XOR/TEST
1 2
| 逻辑运算助记符 reg, imm/reg/mem ;reg <- reg 逻辑运算助记符 imm/reg/mem 逻辑运算助记符 mem, imm/reg ;mem <- mem 逻辑运算助记符 imm/reg
|
所有双操作数的逻辑指令均设置 CF=OF=0
# NOT
1
| not reg/mem ;reg/mem <- ~reg/mem
|
# 移位指令
根据移入的位设置进位标志 CF
,根据移位后的结果影响 SF ZF PF
;当进行 1 位移动,根据最高符号位有变化设置 OF = 1
,移位超过 1 位, OF
不确定
1 2 3 4
| shl reg/mem, 1/cl ;最低位补0, 最高位进入cf shr reg/mem, 1/cl ;最高位补0, 最低位进入cf sal reg/mem, 1/cl ;与shl相同 sar reg/mem, 1/cl ;最高位不变, 最低位进入cf
|
# 循环移位指令
根据移入的位设置进位标志 CF
,不影响 SF ZF PF AF
,对 OF
与移位指令影响一致
1 2 3 4
| rol reg/mem, 1/cl ;不带进位循环左移 ror reg/mem, 1/cl ;不带进位循环右移 rcl reg/mem, 1/cl ;带进位循环左移 rcr reg/mem, 1/cl ;带进位循环右移
|
# 控制转移指令
三种寻址方式:
![]()
比较无符号数的高低:
助记符 |
标志位 |
说明 |
JB/JNAE |
CF = 1 |
低于 / 不高于等于转移 |
JNB/JAE |
CF = 0 |
不低于 / 高于等于转移 |
JBE/JNA |
CF = 1 或 ZF = 1 |
低于等于 / 不高于转移 |
JNBE/JA |
CF = 0 且 ZF = 0 |
不低于等于 / 高于 |
比较有符号数的大小:
助记符 |
标志位 |
说明 |
JL/JNGE |
SF=OF |
小于 / 不大于等于转移 |
JNL/JGE |
SF = OF |
不小于 / 大于等于转移 |
JLE/JNG |
SF=OF 或 ZF = 1 |
小于等于 / 不大于转移 |
JNLE/JG |
SF = OF 且 ZF = 0 |
不小于等于 / 大于转移 |
# 子程序指令
# CALL
1 2 3 4 5 6 7 8
| ;段内调用 call label ;sp <- sp - 2, ss:[sp] <- ip, ip <- ip + 16 call r16/m16 ;sp <- sp - 2, ss:[sp] <- ip, ip <- r16/m16 ;段间调用 call far ptr label ;sp <- sp - 2, ss:[sp] <- cs, sp <- sp - 2, ss:[sp] <- ip ;ip <- label的偏移地址, cs <- label的段地址 call far ptr mem ;sp <- sp - 2, ss:[sp] <- cs, sp <- sp - 2, ss[sp] <- ip ;ip <- [mem], cs <- [mem + 2]
|
# RET
1 2 3 4 5 6
| ;段内返回 ret ;ip <- ss:[sp], sp <- sp + 2 ret i16 ;ip <- ss:[sp], sp <- sp + 2, sp <- sp + i16 ;段间返回 ret ;ip <- ss:[sp], sp <- sp + 2, cs <- ss:[sp], sp <- sp + 2 ret i16 ;ip <- ss:[sp], sp <- sp + 2, cs <- ss:[sp], sp <- sp + i16
|
# 中断指令
# 外部中断
外部中断 —— 来自 CPU 之外的原因引起的中断,又可以分成
- 可屏蔽中断:可由 CPU 的中断允许标志 IF 控制
- 非屏蔽中断:不受 CPU 的中断允许标志 IF 控制
# 内部中断
内部中断 ——CPU 内部执行程序引起的中断,又可以分成:
- 除法错中断:执行除法指令,结果溢出产生的 0 号中断
- 指令中断:执行中断调用指令
INT i8
产生的 i8 号中断
- 断点中断:用于断点调试(
INT 3
)的 3 号中断
- 溢出中断:执行溢出中断指令
into
,OF=1 产生的 4 号中断
- 单步中断:TF=1 在每条指令执行后产生的 1 号中断