C 编译器制作入门

附录 1:x86-64 指令集速查表

附录 1:x86-64 指令集速查表

本附录汇总了本书实现编译器时用到的 x86-64 指令和寄存器约定。

这里不是完整的指令集手册,而是为了便于查阅本书示例而整理的最小集合。

表中使用以下记法:

整数寄存器列表

下表列出 x86-64 的通用整数寄存器,以及同一寄存器在不同位宽下的别名。

64 位32 位16 位8 位
RAXEAXAXAL
RDIEDIDIDIL
RSIESISISIL
RDXEDXDXDL
RCXECXCXCL
RBPEBPBPBPL
RSPESPSPSPL
RBXEBXBXBL
R8R8DR8WR8B
R9R9DR9WR9B
R10R10DR10WR10B
R11R11DR11WR11B
R12R12DR12WR12B
R13R13DR13WR13B
R14R14DR14WR14B
R15R15DR15WR15B

System V AMD64 ABI 中,常用寄存器约定如下。表中的“调用者保存”表示:函数调用后,被调用函数不保证这些寄存器仍保持原值;如果调用者后面还要使用它们,就必须在调用前自行保存。

寄存器典型用途调用者保存
RAX返回值;可变参数函数中也用于传递向量参数个数
RDI第 1 个整数/指针参数
RSI第 2 个整数/指针参数
RDX第 3 个整数/指针参数
RCX第 4 个整数/指针参数
R8第 5 个整数/指针参数
R9第 6 个整数/指针参数
R10临时寄存器
R11临时寄存器
RBP基址指针
RSP栈指针
RBX通用保存寄存器
R12-R15通用保存寄存器

调用函数时,执行 call 指令之前,栈指针 RSP 必须满足 ABI 要求的 16 字节对齐。没有正确对齐时,某些库函数可能崩溃。

内存访问

指令含义
mov dst, [r64]r64 指向的地址读取值到 dst
mov [r64], srcsrc 的值写入 r64 指向的地址
push r64/immRSP -= 8,然后把值写入栈顶
pop r64从栈顶读入 r64,然后 RSP += 8

函数调用

指令含义
call label把返回地址压栈,然后跳转到 label
call r64把返回地址压栈,然后跳转到 r64 中保存的地址
ret从栈顶弹出返回地址,并跳转到该地址
leave等价于 mov rsp, rbp 后接 pop rbp

条件分支

指令序列含义
cmp reg1, reg2/imm
je label
如果 reg1 == reg2/imm,跳转到 label
cmp reg1, reg2/imm
jne label
如果 reg1 != reg2/imm,跳转到 label
cmp reg1, reg2/imm
jl label
如果 reg1 < reg2/imm,跳转到 label(有符号比较)
cmp reg1, reg2/imm
jle label
如果 reg1 <= reg2/imm,跳转到 label(有符号比较)

条件赋值

指令序列含义
cmp reg1, reg2/imm
sete al
movzb eax, al
RAX = (reg1 == reg2/imm) ? 1 : 0
cmp reg1, reg2/imm
setne al
movzb eax, al
RAX = (reg1 != reg2/imm) ? 1 : 0
cmp reg1, reg2/imm
setl al
movzb eax, al
RAX = (reg1 < reg2/imm) ? 1 : 0(有符号比较)
cmp reg1, reg2/imm
setle al
movzb eax, al
RAX = (reg1 <= reg2/imm) ? 1 : 0(有符号比较)

整数与逻辑运算

指令含义
add dst, src/immdst = dst + src/imm
sub dst, src/immdst = dst - src/imm
mul srcRDX:RAX = RAX * src(无符号)
imul dst, srcdst = dst * src(有符号)
div r32EAX = EDX:EAX / r32EDX = EDX:EAX % r32
div r64RAX = RDX:RAX / r64RDX = RDX:RAX % r64
idiv r32/r64div 的有符号版本
cqoRAX 符号扩展到 RDX:RAX
and dst, srcdst = dst & src
or dst, srcdst = dst | src
xor dst, srcdst = dst ^ src
neg dstdst = -dst
not dstdst = ~dst
shl dst, imm/CL逻辑左移。移位量可以是立即数,也可以放在 CL
shr dst, imm/CL逻辑右移,高位补 0
sar dst, imm/CL算术右移,高位补符号位
lea dst, [src]计算地址表达式 [src],不访问内存,把地址结果放入 dst
movsb dst, r8把 8 位值符号扩展后写入 dst
movzb dst, r8把 8 位值零扩展后写入 dst
movsw dst, r16把 16 位值符号扩展后写入 dst
movzw dst, r16把 16 位值零扩展后写入 dst