跳转至

x86-64

x86-64 寄存器

x86-64 有 16 个通用寄存器,大小均为 64-bit,但是可以按需使用不同大小的部分寄存器:

64-bit 32-bit 16-bit 8-bit 常见用途
rax eax ax ah, al 返回值、累加器
rbx ebx bx bh, bl 通用寄存器,常作保存寄存器
rcx ecx cx ch, cl 计数器、移位计数、参数寄存器
rdx edx dx dh, dl 数据寄存器、参数寄存器
rsi esi si sil 源索引、参数寄存器
rdi edi di dil 目标索引、参数寄存器
rbp ebp bp bpl 栈帧基址指针
rsp esp sp spl 栈顶指针
r8 r8d r8w r8b 扩展通用寄存器
r9 r9d r9w r9b 扩展通用寄存器
r10 r10d r10w r10b 扩展通用寄存器
r11 r11d r11w r11b 扩展通用寄存器
r12 r12d r12w r12b 扩展通用寄存器
r13 r13d r13w r13b 扩展通用寄存器
r14 r14d r14w r14b 扩展通用寄存器
r15 r15d r15w r15b 扩展通用寄存器

特殊寄存器

寄存器 说明 常见用途
rip 指令指针寄存器 指向下一条将要执行的指令
rflags 标志寄存器 保存运算结果状态和控制标志
cs 代码段寄存器 当前代码段选择子
ss 栈段寄存器 当前栈段选择子
ds 数据段寄存器 历史遗留数据段寄存器,64 位下作用弱化
es 附加段寄存器 历史遗留附加段寄存器,64 位下作用弱化
fs 段寄存器 常用于线程局部存储(TLS)
gs 段寄存器 常用于线程/内核相关数据

其中 rflags 中具体的标志位如下:

标志位 名称 含义
ZF Zero Flag 结果是否为 0
CF Carry Flag 进位/借位标志,常用于无符号比较
SF Sign Flag 符号标志,结果最高位
OF Overflow Flag 有符号溢出标志
PF Parity Flag 奇偶校验标志
AF Auxiliary Carry Flag 辅助进位标志,较少手工关注

调用约定

在 System V AMD64 ABI (Linux、macOS 等)下,函数的传参一般有 6 个整数/指针参数和 8 个浮点参数通过寄存器传递,超过部分通过栈传递。

参数序号 寄存器
第 1 个 rdi
第 2 个 rsi
第 3 个 rdx
第 4 个 rcx
第 5 个 r8
第 6 个 r9

浮点参数:

  • xmm0 ~ xmm7

而在 Windows x64 ABI 下,函数的前 4 个整数/指针参数通过寄存器传递,超过部分通过栈传递。

参数序号 寄存器
第 1 个 rcx
第 2 个 rdx
第 3 个 r8
第 4 个 r9

浮点参数:

  • xmm0 ~ xmm3

它们的返回值寄存器都是:

类型 返回寄存器
整数 / 指针 rax
浮点数 xmm0

寄存器保存规则

System V AMD64

  • Caller-saved

    • rax
    • rcx
    • rdx
    • rsi
    • rdi
    • r8 ~ r11
  • Callee-saved

    • rbx
    • rbp
    • r12 ~ r15

Windows x64

  • Caller-saved

    • rax
    • rcx
    • rdx
    • r8
    • r9
    • r10
    • r11
  • Callee-saved

    • rbx
    • rbp
    • rdi
    • rsi
    • r12 ~ r15

指令

0. 最常见指令总表

指令 类型 简要说明
mov dest, src 数据传送 复制数据
lea dest, src 地址计算 计算有效地址
movzx dest, src 数据传送 零扩展复制
movsx dest, src 数据传送 符号扩展复制
add dest, src 算术运算 加法
sub dest, src 算术运算 减法
inc dest 算术运算 自增 1
dec dest 算术运算 自减 1
imul dest, src 算术运算 有符号乘法
mul src 算术运算 无符号乘法
idiv src 算术运算 有符号除法
div src 算术运算 无符号除法
neg dest 算术运算 取相反数
and dest, src 逻辑运算 按位与
or dest, src 逻辑运算 按位或
xor dest, src 逻辑运算 按位异或
not dest 逻辑运算 按位取反
test dest, src 测试 与运算并设置标志位
cmp dest, src 比较 减法比较并设置标志位
shl dest, imm/cl 移位 逻辑左移
shr dest, imm/cl 移位 逻辑右移
sar dest, imm/cl 移位 算术右移
rol dest, imm 循环移位 循环左移
ror dest, imm 循环移位 循环右移
jmp label 跳转 无条件跳转
je label 条件跳转 相等时跳转
jne label 条件跳转 不相等时跳转
ja label 条件跳转 无符号大于时跳转
jb label 条件跳转 无符号小于时跳转
jg label 条件跳转 有符号大于时跳转
jl label 条件跳转 有符号小于时跳转
call label 流程控制 调用函数
ret 流程控制 函数返回
push src 栈操作 压栈
pop dest 栈操作 出栈
nop 空操作 不执行有效操作

1. 数据传送类

指令 类型 简要说明
mov dest, src 数据传送 src 复制到 dest
lea dest, src 地址计算 计算有效地址并写入 dest,常用于地址运算或加法优化
xchg dest, src 数据交换 交换两个操作数的值
movzx dest, src 零扩展 将较小操作数复制到较大寄存器,高位补 0
movsx dest, src 符号扩展 将较小有符号操作数扩展到较大寄存器
cdqe 符号扩展 eax 符号扩展到 rax
cqo 符号扩展 rax 符号扩展到 rdx:rax,常用于除法前准备

2. 算术运算类

指令 类型 简要说明
add dest, src 算术运算 src 加到 dest,结果存回 dest
sub dest, src 算术运算 dest 减去 src,结果存回 dest
inc dest 算术运算 dest 自增 1
dec dest 算术运算 dest 自减 1
imul dest, src 算术运算 有符号乘法,常见形式为将乘积写回目标寄存器
mul src 算术运算 无符号乘法,使用隐含寄存器参与
idiv src 算术运算 有符号除法,使用隐含寄存器参与
div src 算术运算 无符号除法,使用隐含寄存器参与
neg dest 算术运算 取相反数,即 dest = -dest
adc dest, src 算术运算 带进位加法
sbb dest, src 算术运算 带借位减法

除法常见隐含寄存器

操作数位宽 被除数位置 余数
8 位 AX AL AH
16 位 DX:AX AX DX
32 位 EDX:EAX EAX EDX
64 位 RDX:RAX RAX RDX

3. 逻辑与位运算

指令 类型 简要说明
and dest, src 逻辑运算 按位与
or dest, src 逻辑运算 按位或
xor dest, src 逻辑运算 按位异或
not dest 逻辑运算 按位取反
test dest, src 比较/测试 按位与并设置标志位,不保存结果
shl dest, imm 移位 逻辑左移指定立即数位数
shl dest, cl 移位 cl 指定的位数逻辑左移
sal dest, imm 移位 算术左移,实际效果通常与 shl 相同
shr dest, imm 移位 逻辑右移,左侧补 0
shr dest, cl 移位 cl 指定的位数逻辑右移
sar dest, imm 移位 算术右移,保留符号位
sar dest, cl 移位 cl 指定的位数算术右移
rol dest, imm 循环移位 循环左移
ror dest, imm 循环移位 循环右移

4. 比较与测试

指令 类型 简要说明
cmp dest, src 比较 执行 dest - src,只更新标志位,不保存结果
test dest, src 测试 执行 dest & src,只更新标志位,不保存结果

5. 跳转与流程控制

指令 类型 简要说明
jmp label 跳转 无条件跳转
call label 函数调用 将返回地址压栈后跳转到目标函数
ret 函数返回 从栈顶弹出返回地址并跳回
nop 空操作 不执行实际操作,常用于对齐或补丁

6. 栈操作

指令 类型 简要说明
push src 栈操作 将操作数压入栈顶
pop dest 栈操作 从栈顶弹出数据到目标操作数

7. 条件跳转

指令 条件 常见含义
je label / jz label ZF = 1 相等 / 结果为 0 时跳转
jne label / jnz label ZF = 0 不相等 / 结果非 0 时跳转
ja label CF=0ZF=0 无符号大于
jae label CF=0 无符号大于等于
jb label CF=1 无符号小于
jbe label CF=1ZF=1 无符号小于等于
jg label ZF=0SF=OF 有符号大于
jge label SF=OF 有符号大于等于
jl label SF≠OF 有符号小于
jle label ZF=1SF≠OF 有符号小于等于

常见函数栈帧

GAS
1
2
3
4
5
6
7
push rbp
mov rbp, rsp
sub rsp, 0x20
... 函数体 ...
mov rsp, rbp
pop rbp
ret

含义

  1. push rbp

    • 保存旧的栈帧基址
  2. mov rbp, rsp

    • 建立新的栈帧
  3. sub rsp, 0x20

    • 为局部变量分配栈空间
  4. mov rsp, rbp

    • 恢复栈顶指针,准备返回
  5. pop rbp

    • 恢复栈顶指针和旧的栈帧基址,准备返回
  6. ret

    • 从栈顶弹出返回地址并跳回