General-Purpose Registers in 64-mode
在64位模式下,有16个64位宽通用寄存器(32位模式是8个通用寄存器),默认的操作数宽度是32位(注:与32位模式相同)。但是,通用寄存器保存32位或64位的操作数。如果指定了32位操作数,则可以使用EAX/EBX/ECX/EDX/EBP/ESP/ESI/EDI和新增的R8D~R15D(注:这里D表示Doubledord,32比特宽)。如果是64位的操作数,则可以使用RAX/RBX/RCX/RDX/RBP/RSP/RSI/RDI和新增的R8~R15。所有的这些寄存器都可以按字节/单字/双字/四字/八字为单位访问。REX指令前缀用来生成64位的操作数,或者用于访问寄存器R8~R15。
当从64位模式切换到兼容模式,再返回到64位模式后,仅存在于64位模式下的寄存器(R8~R15和XMM8~XMM15)中的值会保持不变。但是如果从64位模式切换到兼容模式,再切换到传统模式(注:即32位保护模式或SMM模式)或实模式,最后通过兼容模式返回到64位模式后,R8~R15和XMM8~XMM15寄存器中的值是未定义的(undefined)。
表:可寻址的通用寄存器
寄存器类型 | 无REX前缀 | 有REX前缀 |
字节寄存器 | AH/AL, BH/BL, CH/CL, DH/DL | AL/BL/CL/DL, BPL/SPL/SIL/DIL, R8L~R15L |
单字寄存器 | AX/BX/CX/DX/BP/SP/SI/DI | AX/BX/CX/DX/BP/SP/SI/DI, R8W~R15W |
双字寄存器 | EAX/EBX/ECX/EDX/EBP/ESP/ESI/EDI | EAX/EBX/ECX/EDX/EBP/ESP/ESI/EDI, R8D~R15D |
四字寄存器 | N.A. | RAX/RBX/RCX/RDX/RBP/RSP/RSI/RDI, R8~R15 |
(参看上表)在64位模式下,对字节寄存器的访问有所限制。指令不能同时引用传统的高字节寄存器(例如AH/BH/CH/DH)与新字节寄存器(例如RAX寄存器的低字节)。但是指令可以同时引用传统的低字节寄存器(例如AL/BL/CL/DL)与新字节寄存器(例如R8寄存器的低字节,或RBP)。对于使用REX前缀的指令,处理器架构通过转换高字节引用(AH/BH/CH/DH)到低字节引用(BPL/SPL/DIL/SIL:RBP/RSP/RDI/RSI的最低字节)来强制实施这种限制。TODO: 找几个例子。
当在64位模式下时,操作数的宽度决定目标(通用)寄存器的有效比特位数:
- 64位操作数生成64位的结果,保存在64位宽的目标寄存器中
- 32位操作数生成32位的结果,通过零扩展,保存在64位宽的目标寄存器中
- 8位和16位操作数生成8位或16位的结果。目标寄存器中的对应的最高的56比特位或48比特位保持指令执行前的值,不会被修改。如果8位/16位的运算结果是用于64位地址计算,需要显式地将结果值符号扩展到完整的64位宽。
因为64位通用寄存器的高32比特位在32位模式下无定义,所以当从64位模式切换到32位模式(即保护模式或兼容模式)后,任何通用寄存器的高32比特位不会被保存。当从64位模式切换到32位模式时,软件不要依赖处理器保存这些比特位。