x64 体系结构是 x86 的向后兼容扩展。 它提供新的 64 位模式和旧版 32 位模式,与 x86 相同。
术语“x64”包括 AMD 64 和 Intel64。 指令集几乎完全相同。
寄存器
x64 将 x86 的 8 个常规用途寄存器扩展到 64 位,并添加了 8 个新的 64 位寄存器。 64 位寄存器的名称以“r”开头。 例如, eax 的 64 位扩展称为 rax。 新寄存器命名为 r8 到 r15。
每个寄存器的低 32 位、16 位和 8 位可以在操作数中直接寻址。 这包括寄存器,如 esi,其较低的 8 位以前无法寻址。 下表指定 64 位寄存器下半部分的程序集语言名称。
| 64 位寄存器 | 低 32 位 | 低 16 位 | 低 8 位 |
|---|---|---|---|
| rax | eax | ax | 铝 |
| rbx | ebx | bx | bl |
| rcx | ecx | cx | cl |
| rdx | edx | dx | dl |
| rsi | esi | 四 | sil |
| rdi | edi | 地 | dil |
| rbp | ebp | 血压 | 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 和 flags 寄存器已分别扩展到 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。
为 64 位即时常量或常量地址添加了一种特殊形式的 mov 指令。 对于所有其他指令,即时常量或常量地址仍为 32 位。
x64 提供了一种新的RIP相对寻址模式。 引用单个常量地址的指令被编码为基于 rip 的偏移量。 例如, mov rax、[addr] 指令将从 addr + rip 开始的 8 个字节移动到 rax。
指令(如 jmp、 调用、 推送和 pop)隐式引用指令指针,堆栈指针将它们视为 x64 上的 64 位寄存器。