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 |
浮点参数:
而在 Windows x64 ABI 下,函数的前 4 个整数/指针参数通过寄存器传递,超过部分通过栈传递。
| 参数序号 |
寄存器 |
| 第 1 个 |
rcx |
| 第 2 个 |
rdx |
| 第 3 个 |
r8 |
| 第 4 个 |
r9 |
浮点参数:
它们的返回值寄存器都是:
| 类型 |
返回寄存器 |
| 整数 / 指针 |
rax |
| 浮点数 |
xmm0 |
寄存器保存规则
System V AMD64
-
Caller-saved
- rax
- rcx
- rdx
- rsi
- rdi
- r8 ~ r11
-
Callee-saved
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=0 且 ZF=0 |
无符号大于 |
jae label |
CF=0 |
无符号大于等于 |
jb label |
CF=1 |
无符号小于 |
jbe label |
CF=1 或 ZF=1 |
无符号小于等于 |
jg label |
ZF=0 且 SF=OF |
有符号大于 |
jge label |
SF=OF |
有符号大于等于 |
jl label |
SF≠OF |
有符号小于 |
jle label |
ZF=1 或 SF≠OF |
有符号小于等于 |
常见函数栈帧
| GAS |
|---|
| push rbp
mov rbp, rsp
sub rsp, 0x20
... 函数体 ...
mov rsp, rbp
pop rbp
ret
|
含义
-
push rbp
-
mov rbp, rsp
-
sub rsp, 0x20
-
mov rsp, rbp
-
pop rbp
-
ret