x86 汇编速查表
本章提供 x86 汇编常用指令、寄存器和概念的快速参考。
通用寄存器
x86-64 寄存器
| 64 位 | 32 位 | 16 位 | 8 位低 | 8 位高 | 用途 |
|---|---|---|---|---|---|
| RAX | EAX | AX | AL | AH | 累加器、返回值 |
| RBX | EBX | BX | BL | BH | 基址寄存器 |
| RCX | ECX | CX | CL | CH | 计数器 |
| RDX | EDX | DX | DL | DH | 数据寄存器 |
| RSI | ESI | SI | SIL | - | 源变址 |
| RDI | EDI | DI | DIL | - | 目标变址 |
| RBP | EBP | BP | BPL | - | 栈帧指针 |
| RSP | ESP | SP | SPL | - | 栈指针 |
| R8-R15 | R8D-R15D | R8W-R15W | R8B-R15B | - | 通用寄存器 |
调用约定(Linux x86-64)
| 寄存器 | 用途 | 保存者 |
|---|---|---|
| RAX | 返回值 | 调用者 |
| RDI | 第 1 个参数 | 调用者 |
| RSI | 第 2 个参数 | 调用者 |
| RDX | 第 3 个参数 | 调用者 |
| RCX | 第 4 个参数 | 调用者 |
| R8 | 第 5 个参数 | 调用者 |
| R9 | 第 6 个参数 | 调用者 |
| RBX | 通用 | 被调用者 |
| RBP | 栈帧 | 被调用者 |
| R12-R15 | 通用 | 被调用者 |
| R10-R11 | 临时 | 调用者 |
标志寄存器
| 标志 | 名称 | 含义 |
|---|---|---|
| CF | 进位标志 | 无符号溢出 |
| ZF | 零标志 | 结果为零 |
| SF | 符号标志 | 结果为负 |
| OF | 溢出标志 | 有符号溢出 |
| PF | 奇偶标志 | 1 的个数为偶 |
| AF | 辅助进位 | 低 4 位进位 |
| DF | 方向标志 | 字符串方向 |
数据传送指令
mov dest, src ; 复制数据
movzx dest, src ; 零扩展传送
movsx dest, src ; 符号扩展传送
xchg op1, op2 ; 交换
lea dest, [addr] ; 加载有效地址
push src ; 压栈
pop dest ; 出栈
pushf/popf ; 标志寄存器操作
算术指令
add dest, src ; 加法
adc dest, src ; 带进位加法
sub dest, src ; 减法
sbb dest, src ; 带借位减法
inc dest ; 自增
dec dest ; 自减
neg dest ; 取负
cmp op1, op2 ; 比较(设置标志位)
mul src ; 无符号乘法(RDX:RAX = RAX * src)
imul dest, src ; 有符号乘法
div src ; 无符号除法(RAX = RDX:RAX / src)
idiv src ; 有符号除法
逻辑指令
and dest, src ; 与运算
or dest, src ; 或运算
xor dest, src ; 异或运算
not dest ; 取反
test op1, op2 ; 测试(AND 但不保存结果)
移位指令
shl/shr dest, count ; 逻辑左移/右移
sal/sar dest, count ; 算术左移/右移
rol/ror dest, count ; 循环左移/右移
rcl/rcr dest, count ; 带进位循环移位
条件跳转指令
常用条件跳转
| 指令 | 条件 | 描述 |
|---|---|---|
| JMP | 无条件 | 无条件跳转 |
| JE/JZ | ZF=1 | 相等/零 |
| JNE/JNZ | ZF=0 | 不等/非零 |
| JL/JNGE | SF≠OF | 有符号小于 |
| JLE/JNG | SF≠OF 或 ZF=1 | 有符号小于等于 |
| JG/JNLE | SF=OF 且 ZF=0 | 有符号大于 |
| JGE/JNL | SF=OF | 有符号大于等于 |
| JB/JNAE/JC | CF=1 | 无符号小于 |
| JBE/JNA | CF=1 或 ZF=1 | 无符号小于等于 |
| JA/JNBE | CF=0 且 ZF=0 | 无符号大于 |
| JAE/JNB/JNC | CF=0 | 无符号大于等于 |
| JS | SF=1 | 为负 |
| JNS | SF=0 | 为正 |
| JO | OF=1 | 溢出 |
| JNO | OF=0 | 无溢出 |
条件设置指令
setz/sete dest ; 等于时设置为 1
setnz/setne dest ; 不等于时设置为 1
setl/setg dest ; 有符号小于/大于
setb/seta dest ; 无符号小于/大于
条件传送指令
cmove/cmovz dest, src ; 相等时传送
cmovne/cmovnz dest, src ; 不等时传送
cmovl/cmovg dest, src ; 有符号小于/大于时传送
cmovb/cmova dest, src ; 无符号小于/大于时传送
循环指令
loop label ; RCX--,若 RCX≠0 则跳转
loope/loopz label ; RCX--,若 RCX≠0 且 ZF=1 则跳转
loopne/loopnz label ; RCX--,若 RCX≠0 且 ZF=0 则跳转
字符串指令
movsb/w/d/q ; 传送字节/字/双字/四字
cmpsb/w/d/q ; 比较字节/字/双字/四字
scasb/w/d/q ; 扫描字节/字/双字/四字
stosb/w/d/q ; 存储字节/字/双字/四字
lodsb/w/d/q ; 加载字节/字/双字/四字
rep ; 重复(RCX 次)
repe/repz ; 相等时重复
repne/repnz ; 不等时重复
cld ; DF=0(递增方向)
std ; DF=1(递减方向)
过程调用指令
call addr ; 调用过程
ret ; 返回
ret n ; 返回并清理 n 字节参数
leave ; 恢复栈帧(mov rsp,rbp; pop rbp)
寻址模式
[imm] ; 直接寻址
[reg] ; 寄存器间接寻址
[reg + disp] ; 寄存器相对寻址
[reg1 + reg2] ; 变址寻址
[reg1 + reg2*scale] ; 比例变址寻址
[reg1 + reg2*scale + disp] ; 完整寻址
[rip + disp] ; RIP 相对寻址
比例因子:1, 2, 4, 8
Linux 系统调用(x86-64)
系统调用约定
| 寄存器 | 用途 |
|---|---|
| RAX | 系统调用号 |
| RDI | 第 1 个参数 |
| RSI | 第 2 个参数 |
| RDX | 第 3 个参数 |
| R10 | 第 4 个参数 |
| R8 | 第 5 个参数 |
| R9 | 第 6 个参数 |
| RAX | 返回值 |
常用系统调用
| 编号 | 名称 | 描述 |
|---|---|---|
| 0 | read | 读取文件 |
| 1 | write | 写入文件 |
| 2 | open | 打开文件 |
| 3 | close | 关闭文件 |
| 9 | mmap | 内存映射 |
| 39 | getpid | 获取进程 ID |
| 57 | fork | 创建进程 |
| 59 | execve | 执行程序 |
| 60 | exit | 退出进程 |
| 62 | kill | 发送信号 |
NASM 伪指令
数据定义
db value ; 定义字节
dw value ; 定义字
dd value ; 定义双字
dq value ; 定义四字
resb count ; 保留字节
resw count ; 保留字
resd count ; 保留双字
resq count ; 保留四字
equ value ; 定义常量
times n db value ; 重复定义
段定义
section .data ; 已初始化数据段
section .bss ; 未初始化数据段
section .text ; 代码段
section .rodata ; 只读数据段
其他伪指令
global symbol ; 导出符号
extern symbol ; 导入符号
align n ; 对齐
%define name value ; 定义宏
常用技巧
快速清零
xor eax, eax ; EAX = 0
xor rax, rax ; RAX = 0
快速判断零
test eax, eax ; 检查 EAX 是否为 0
jz is_zero
快速乘除
shl eax, 1 ; EAX * 2
shl eax, 2 ; EAX * 4
shl eax, 3 ; EAX * 8
shr eax, 1 ; EAX / 2(无符号)
sar eax, 1 ; EAX / 2(有符号)
lea eax, [eax + eax*2] ; EAX * 3
lea eax, [eax + eax*4] ; EAX * 5
绝对值
; EAX 的绝对值
cdq ; 符号扩展到 EDX
xor eax, edx ; 如果为负,取反
sub eax, edx ; 如果为负,加 1
最小/最大值
; EAX = max(EAX, EBX)
cmp eax, ebx
cmovl eax, ebx
; EAX = min(EAX, EBX)
cmp eax, ebx
cmovg eax, ebx
编译命令
NASM 编译
# 生成 64 位 ELF 目标文件
nasm -f elf64 program.asm -o program.o
# 生成 32 位 ELF 目标文件
nasm -f elf32 program.asm -o program.o
# 生成列表文件
nasm -f elf64 -l program.lst program.asm
链接
# 链接为可执行文件
ld program.o -o program
# 链接 C 库
gcc program.o -o program
# 静态链接
ld program.o -o program -lc -static
调试
# 使用 GDB 调试
gdb ./program
# 常用 GDB 命令
break main # 设置断点
run # 运行
info registers # 查看寄存器
x/10i $rip # 查看指令
stepi # 单步执行
continue # 继续执行
指令长度
| 指令类型 | 长度 |
|---|---|
| 前缀 | 0-4 字节 |
| 操作码 | 1-3 字节 |
| ModR/M | 0-1 字节 |
| SIB | 0-1 字节 |
| 偏移量 | 0-4 字节 |
| 立即数 | 0-4 字节 |
总长度:1-15 字节