x64 体系结构是 x86 的向后兼容扩展,提供与 x86 相同的新 64 位模式和旧版 32 位模式。 此体系结构将 x86 的 8 个常规用途寄存器扩展到 64 位,添加了 8 个新寄存器,并为新式 64 位编程引入了增强的调用约定和寻址模式。
术语“x64”包括 AMD64 和 Intel 64。 指令集几乎完全相同。
寄存器
x64 将 x86 的八个常规用途寄存器扩展到 64 位,并添加了 8 个新的 64 位寄存器。 64 位寄存器的名称以“r”开头。 例如, eax 的 64 位扩展称为 rax。 新寄存器命名为 r8 到 r15。
每个寄存器的低 32 位、16 位和 8 位可以在操作数中直接寻址。 这种直接可寻址性包括 esi 等寄存器,其较低的 8 位以前无法寻址。 下表指定 64 位寄存器下半部分的程序集语言名称。
| 64 位寄存器 | 低 32 位 | 低 16 位 | 较低的 8 位fix |
|---|---|---|---|
rax |
eax |
ax |
al |
rbx |
ebx |
bx |
bl |
rcx |
ecx |
cx |
cl |
rdx |
edx |
dx |
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 |
输出到 32 位子寄存器的操作会自动零扩展到整个 64 位寄存器。 输出到 8 位或 16 位子寄存器的操作不会进行零拓展(此行为与 x86 兼容)。
高 8 位 ax、 bx、 cx 和 dx 仍可寻址为 ah、 bh、 ch 和 dh ,但不能用于所有类型的作数。
指令指针 eip 和 标志 寄存器分别扩展到 64 位(rip 和 rflags)。
x64 处理器还提供多个浮点寄存器集:
8 个 80 位 x87 寄存器。
8 个 64 位 MMX 寄存器。 (这些寄存器与 x87 寄存器重叠。
8 个 128 位 SSE 寄存器的原始集增加到 16。
调用约定
与 x86 体系结构不同,C/C++ 编译器仅支持 x64 上的一个调用约定。 此调用约定利用了 x64 上可用的寄存器增多的优势:
前四个整数或指针参数在 rcx、 rdx、 r8 和 r9 寄存器中传递。
前四个浮点参数在前四个 SSE 寄存器 xmm0-xmm3 中传递。
调用方为在寄存器中传递的参数保留堆栈上的空间。 调用的函数可以使用此空间将寄存器的内容溢出到堆栈。
您可以在堆栈上传递其他任何参数。
整数或指针返回值在 rax 寄存器中返回,而浮点返回值在 xmm0 中返回。
rax、 rcx、 rdx、 r8-r11 是可变的。
rbx、rbp、rdi、rsi、r12-r15 是非易失性。
C++的调用约定类似。 此指针作为隐式第一个参数传递。 接下来的三个参数在剩余寄存器中传递,其余参数在堆栈上传递。
寻址模式
64 位模式下的寻址模式与 x86 类似,但与 x86 不同。
引用 64 位寄存器的指令会自动以 64 位精度进行操作。 例如, mov rax、[rbx] 将 8 个字节从 rbx 开始移动到 rax。
mov 指令的特殊形式适用于 64 位即时常量或常量地址。 对于所有其他指令,即时常量或常量地址仍为 32 位。
x64 提供了一种新的RIP相对寻址模式。 将单个常量地址的指令编码为相对于rip的偏移量。 例如, mov rax、[addr] 指令将从 addr + rip 开始的 8 个字节移动到 rax。
指令(如 jmp、 调用、 推送和 pop)隐式引用指令指针,堆栈指针将它们视为 x64 上的 64 位寄存器。