汇编语言 8086指令系统整理。
数据传送类指令
通用数据传送指令
传送指令 mov
1 | mov reg/mem, imm ; 立即数送寄存器或主存 |
交换指令 xchg
1 | xchg reg, reg/mem ; 将寄存器与寄存器或主存的内容交换 |
换码指令 xlat
1 | xlat ; al <- ds:[bx+al] |
堆栈操作指令
堆栈是一个”先进后出”的主存区域,位于堆栈段中。
存储方式是:高位栈底,低位栈顶。
进栈指令 push
1 | push r16/m16/seg ; sp <- sp-2, ss:[sp] <- r16/m16/seg |
出栈指令 pop
1 | pop r16/m16/seg ; r16/m16/reg, 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 |
标志位操作
1 | clc ; CF <- 0 |
地址传送指令
有效地址传送指令 lea
1 | lea r16, mem ; r16 <- mem的有效地址EA |
指针传送指令 lds
les
1 | lds r16, mem ; r16 <- mem, ds <- mem+2 |
算术运算类指令
首先了解几个状态标志,它们在算术运算中起着重要作用。
进位标志 CF(Carry Flag):
针对无符号整数运算设计。
当加减运算的结果的最高有效位有进位或借位时,设置CF = 1溢出标志 OF(Overflow Flag):
针对有符号整数运算设计。
当有符号数进行加减运算的结果超出范围时,设置OF = 1零标志 ZF(Zero Flag):
反映运算结果是否为 0,当运算结果为 0 时,设置ZF = 1符号指令 SF(Sign Flag):
反映运算结果是正数还是负数,当运算结果最高位为 1 时,SF = 1奇偶校验 PF(Parity Flag):
反映运算结果最低字节中 1 的个数时偶数还是奇数,为偶数时,PF = 1调整标志 AF(Adjust Flag):
当加减运算时最低半字节有进位或借位时,AF = 1
加法指令 add
1 | add reg, imm/reg/mem ; reg <- res+imm/reg/mem |
带进位加法指令 adc
1 | adc reg, imm/reg/mem ; reg <- res+imm/reg/mem+cf |
增量指令 inc
1 | inc reg/mem ; reg/mem <- reg/mem+1 |
减法指令 sub
1 | sub reg, imm/reg/mem ; reg <- res-imm/reg/mem |
带借位减法指令 sbb
1 | sbb reg, imm/reg/mem ; reg <- res-imm/reg/mem-cf |
减量指令 dec
1 | dec reg/mem ; reg/mem <- reg/mem-1 |
求补指令 neg
1 | neg reg/mem ; reg/mem <- 0-reg/mem |
比较指令 cmp
1 | cmp reg, imm/reg/mem ; reg-imm/reg/mem |
无符号数乘法指令 mul
,有符号数乘法指令 imul
1 | mul r8/m8 ; 无符号字节乘: ax <- al·r8/m8 |
无符号二进制数除法指令 div
,有符号二进制数除法指令 idiv
1 | div r8/m8 ; 无符号数字节除: al <- ax除以r8/m8的商 |
符号扩展指令 cbw
cwd
1 | cbw ; al符号扩展到ax |
位操作类指令
逻辑与指令 and
1 | and dest, src ; dest <- dest&src |
逻辑或指令 or
1 | or dest, src ; dest <- dest|src |
逻辑异或指令 xor
1 | xor dest, src ; dest <- dest^src |
逻辑非指令 not
1 | not reg/mem ; reg/mem <- ~reg/mem |
测试指令 test
1 | test dest, src ; dest&src |
移位指令 shl
shr
sal
sar
1 | shl reg/mem, 1/cl ; 逻辑左移: reg/mem左移1/cl位,最低位补0,最高位进入CF |
循环移位指令 rol
ror
rcl
rcr
1 | rol reg/mem, 1/cl ; 不带进位循环左移 |
控制转移类指令
段内转移是指在当前代码段 64KB 范围内转移,因此不需要改变 CS 段地址,只需更改 IP 偏移地址。
如果转移范围可以用一个 8 位数(-128~127)表达,则形成短转移(short jump)
如果转移范围可以用一个 16 位数表达,则形成近转移(near jump)段间转移是指从当前代码段跳转到另一个代码段,此时需要更改 CS 段地址和 IP 偏移地址。
这种转移也称为远转移(far jump),转移的目标地址用一个 32 位数表达,叫做 32 位远指针,即逻辑地址。
无条件转移指令 jmp
,分为四种格式。
1 | jmp label ; ip <- ip+位移量 |
1 | jmp r16/m16 ; ip <- r16/m16 |
1 | jmp far ptr label ; ip <- label的偏移地址, cs <- label的段地址 |
1 | jmp far ptr mem ; ip <- [mem], cs <- [mem + 2] |
条件转移指令,具体指令如下表给出。
1 | jcc label ; 条件满足,发生转移: ip <- ip+8位位移量 |
- 根据单个条件标志的设置情况转移
指令 | 英文 | 含义 | 格式 | 测试条件 |
---|---|---|---|---|
JZ/JE | jump if zero/equal | 结果为零/相等则转移 | JZ/JE OPR | ZF=1 |
JNZ/JNE | jump if not zero/equal | 结果不为零/不相等则转移 | JNZ/JNE OPR | ZF=0 |
JS | jump if sign | 结果为负则转移 | JS OPR | SF=1 |
JNS | jump if not sign | 结果为正则转移 | JNS OPR | SF=0 |
JO | jump if overflow | 溢出则转移 | JO OPR | OF=1 |
JNO | jump if not overflow | 不溢出则转移 | JNO OPR | OF=0 |
JP/JPE | jump if parity/parity even | 奇偶位为1则转移 | JP/JPE OPR | PF=1 |
JNP/JNPE | jump if not parity/parity even | 奇偶位为0则转移 | JNP/JNPE OPR | PF=0 |
JB/JNAE/JC | jump if below/not above、not equal/carry | 低于/不高于或不等于/进位为1则转移 | JB/JNAE/JC OPR | CF=1 |
JNB/JAE/JNC | jump if not below/ above、equal/not carry | 不低于/高于或等于/进位为零则转移 | JNB/JAE/JNC OPR | CF=0 |
- 比较两个无符号数,并根据比较的结果转移
指令 | 英文 | 含义 | 格式 | 测试条件 | 等价于 |
---|---|---|---|---|---|
JB/JNAE/JC | jump if below/not above、not equal/carry | 低于/不高于或不等于/进位为1则转移 | JB/JNAE/JC OPR | CF=1 | < |
JNB/JAE/JNC | jump if not below/ above、equal/not carry | 不低于/高于或等于/进位为零则转移 | JNB/JAE/JNC OPR | CF=0 | ≥ |
JBE/JNA | jump if below/equal、not above | 低于/等于、不高于则转移 | JBE/JNA OPR | CF并ZF=1 | ≤ |
JNBE/JA | jump if not below/not equal、above | 不低于/不等于、高于则转移 | JNBE/JA OPR | CF并ZF=0 | > |
3. 比较两个带符号数,并根据比较的结果转移
指令 | 英文 | 含义 | 格式 | 测试条件 | 等价于 |
---|---|---|---|---|---|
JL/JNGE | jump if less、not greater/equal | 小于、不大于/不等于则转移 | JL/JNGE OPR | SF异或CF=1 | < |
JNL/JGE | jump if not less、greater/equal | 不小于、大于/等于则转移 | JNL/JGE OPR | SF异或CF=0 | ≥ |
JLE/JNG | jump if less/equal、not greater | 小于/等于、不大于则转移 | JLE/JNG OPR | (SF异或CF)并ZF=1 | ≤ |
JNLE/JG | jump if not less/not equal、 greater | 不小于/不等于、大于则转移 | JNLE/JG OPR | (SF异或CF)并ZF=0 | > |
循环指令。(实际上循环流程可以由前面的转移指令实现)
1 | jcxz label ; cx = 0 则转移,否则顺序执行 |
子程序调用指令 call
,分为四种格式。
1 | call label ; 段内调用,相对寻址: sp <- sp-2, ss:[sp] <- ip |
1 | call r16/m16 ; 段内调用,间接寻址: sp <- sp-2, ss:[sp] <- ip, ip <- r16/m16 |
1 | call far ptr label ; 段间调用,直接寻址: sp <- sp-2, ss:[sp] <- cs |
1 | call far ptr mem ; 段间调用,间接寻址: sp <- sp-2, ss:[sp] <- cs |
子程序返回指令 ret
,分为四种格式。
1 | ret ; 无参数段内返回: ip <- ss:[sp], sp <- sp+2 |
1 | ret i16 ; 有参数段内返回: ip <- ss:[sp], sp <- sp+2, sp <- sp+i16 |
1 | ret ; 无参数段间返回: ip <- ss:[sp], sp <- sp+2 |
1 | ret i16 ; 有参数段间返回: ip <- ss:[sp], sp <- sp+2 |
中断指令
1 | int i8 ; 中断调用指令,产生 i8 号中断 |