x64 体系结构

x64 体系结构是 x86 的向后兼容扩展。 它提供新的 64 位模式和旧版 32 位模式,与 x86 相同。

术语“x64”包括 AMD 64 和 Intel64。 指令集几乎完全相同。

寄存器

x64 将 x86 的 8 个常规用途寄存器扩展到 64 位,并添加了 8 个新的 64 位寄存器。 64 位寄存器的名称以“r”开头。 例如, eax 的 64 位扩展称为 rax。 新寄存器命名为 r8r15

每个寄存器的低 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 位 axbxcxdx 仍可寻址为 ahbhchdh ,但不能用于所有类型的作数。

指令指针 eipflags 寄存器已分别扩展到 64 位(riprflags)。

x64 处理器还提供多个浮点寄存器集:

  • 8 个 80 位 x87 寄存器。

  • 8 个 64 位 MMX 寄存器。 (这些寄存器与 x87 寄存器重叠。

  • 8 个 128 位 SSE 寄存器的原始集增加到 16 个。

调用约定

与 x86 不同,C/C++ 编译器仅支持 x64 上的一个调用约定。 此调用约定利用了 x64 上可用的寄存器增多的优势:

  • 前四个整数或指针参数在 rcxrdxr8r9 寄存器中传递。

  • 前四个浮点参数在前四个 SSE 寄存器 xmm0-xmm3 中传递。

  • 调用方为在寄存器中传递的参数保留堆栈上的空间。 调用的函数可以使用此空间将寄存器的内容溢出到堆栈。

  • 任何其他参数都在堆栈上传递。

  • 整数或指针返回值在 rax 寄存器中返回,而浮点返回值在 xmm0 中返回。

  • raxrcxrdxr8-r11 是可变的。

  • rbxrbp、rdirsir12-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 位寄存器。

另请参阅