# 数据传送指令

# MOV

1
2
3
4
mov reg/mem, imm
mov reg/mem/seg, reg
mov reg/seg, mem
mov reg/mem, seg

注:

  1. 当 src 是 imm,dest 是 mem 时,二者之一必须用 ptr 指定类型
  2. cs 不能做目的操作数,ip 既不能做源操作数也不能做目的操作数
  3. 两个操作数必须类型一致
  4. 立即数不能送直接寻址的内存单元
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

1
lahf	;ah <- flags的低字节

# AH 送标志指令 SAHF

1
sahf	;flags的低字节 <- ah

# 标志进栈指令 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 位无符号数据加减运算结果范围是02N10\sim 2^N - 1

溢出标志 OF 用于表示有符号整数进行加减运算的结果是否超出范围

  • 处理器默认采用补码的形式表示有符号整数,N 位补码表达的范围是2N1+2N11-2^{N-1}\sim+2^{N-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的余数

# 符号扩展指令

CBWAL 的最高有效位扩展到 AH

CWDAX 的内容符号扩展形成 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\neqOF 小于 / 不大于等于转移
JNL/JGE SF = OF 不小于 / 大于等于转移
JLE/JNG SF\neqOF 或 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 号中断