在x86处理器从32位进化到64位的过程中,它们的通用寄存器也做了扩展,从原先的32位扩展到64位,并增加了8个新的通用寄存器,下面我们来看一看这些通用寄存器是如何扩展的。
如图2-3所示,首先,32位的EAX扩展到64位的RAX,比特编号从0到63。其中,低32位还是原先的EAX,低16位还是原先的AX,原先的AH和AL依然可用。
图2-3 寄存器的扩展(一)
32位的EBX扩展到64位的RBX,比特编号从0到63。其中,低32位还是原先的EBX,低16位还是原先的BX,原先的BH和BL依然可用。
32位的ECX扩展到64位的RCX,比特编号从0到63。其中,低32位还是原先的ECX,低16位还是原先的CX,原先的CH和CL依然可用。
32位的EDX扩展到64位的RDX,比特编号从0到63。其中,低32位还是原先的EDX,低16位还是原先的DX,原先的DH和DL依然可用。
如图2-4所示,32位的ESI扩展到64位的RSI,比特编号从0到63。其中,低32位还是原先的ESI,低16位还是原先的SI。在以前的32位处理器上,低8位不可用,但是在64位处理器上是可用的,但也只能在64位模式下使用,叫作SIL。
32位的EDI扩展到64位的RDI,比特编号从0到63。其中,低32位还是原先的EDI,低16位还是原先的DI。在以前的32位处理器上,低8位不可用,但是在64位处理器上是可用的,但也只能在64位模式下使用,叫作DIL。
32位的EBP扩展到64位的RBP,比特编号从0到63。其中,低32位还是原先的EBP,低16位还是原先的BP。在以前的32位处理器上,低8位不可用,但是在64位处理器上是可用的,但也只能在64位模式下使用,叫作BPL。
32位的ESP扩展到64位的RSP,比特编号从0到63。其中,低32位还是原先的ESP,低16位还是原先的SP。在以前的32位处理器上,低8位不可用,但是在64位处理器上是可用的,但也只能在64位模式下使用,叫作SPL。
图2-4 寄存器的扩展(二)
如图2-5所示,在x64架构的处理器上新增加了8个通用寄存器R8~R15。这些寄存器都是64位的,可直接按64位来访问。
图2-5 新增加的寄存器
同时,这些寄存器的低8位可以当成长度为字节的寄存器来用,分别叫作R9B、R10B、R11B、R12B、R13B、R14B和R15B;
这些寄存器的低16位可以当成长度为字的寄存器来用,分别叫作R9W、R10W、R11W、R12W、R13W、R14W和R15W;
这些寄存器的低32位可以当成长度为双字的寄存器来用,分别叫作R9D、R10D、R11D、R12D、R13D、R14D和R15D。
x64架构扩展了原有的通用寄存器,也增加了新的通用寄存器,所以指令集也需要进行扩充。由于x86处理器原有的指令集已经非常庞大,受指令编码方式的限制,只能根据处理器工作模式的不同,来决定哪些寄存器可以使用,哪些不可以使用。
对于我们当前讨论的x64架构来说,如果处理器工作在保护模式或者兼容模式,则它可以使用以下传统的8位、16位、32位通用寄存器:
8位:AH、AL、BH、BL、CH、CL、DH和DL。
16位:AX、BX、CX、DX、SI、DI、BP和SP。
32位:EAX、EBX、ECX、EDX、ESI、EDI、EBP和ESP。
这里有几个保护模式和兼容模式的例子:
首先需要说明一下,伪指令bits并不是用来改变处理器的工作模式的,它只是用来告诉编译器按照指定的模式来生成机器指令。处理器在执行你写的那些指令时是处于什么工作模式,你自己是清楚的,但编译器不清楚,所以你必须用伪指令bits告诉编译器,让它知道后面的指令必须采用哪种格式来编码。
比如这里的bits 32,它指示后面的指令都按32位模式来编码。32位模式包括保护模式和IA-32e兼容模式,所以是要求编译器按保护模式或者IA-32e兼容模式编码以下指令。
因为bits指令是你自己指定的,所以,这意味着,在执行后面的这些指令时,是你假定的处理器已经处于保护模式或者IA-32e兼容模式。
综上所述,在32位模式下,或者说,在保护模式和IA-32e兼容模式下,只能使用传统的8位、16位和32位寄存器,而不能使用x64架构新增的寄存器。
因此,以上的第一条指令是非法的,因为它使用了新的r8b和sil;最后一条指令也是非法的,因为它使用了新的64位寄存器rax和rdx。其他指令都是合法的,用的都是我们以前熟悉的寄存器。
如果处理器工作在64位模式,则它可以使用以下通用寄存器:
8位:AH、AL、BH、BL、CH、CL、DH、DL、SIL、DIL、BPL、SPL、R8B~R15B
16位:AX、BX、CX、DX、SI、DI、BP、SP、R8W~R15W
32位:EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP、R8D~R15D
64位:RAX、RBX、RCX、RDX、RSI、RDI、RBP、RSP、R8~R15
这里有几个64位模式的例子:
伪指令bits 64要求编译器将下面的指令按64位工作模式进行编码。这意味着,在执行下面这些指令前,你要确保处理器已经工作在64位模式。
在64位模式下,对字节长度的寄存器有一些使用上的限制,寄存器的访问限制起源于64位模式下的指令编码规则。比如,不能在指令中同时使用传统的高字节寄存器和新增的字节寄存器。所以前两条指令是非法的。
但是,传统的高字节寄存器和低字节寄存器依然可以同时使用,比如第3条指令。
除以上限制外,64位模式可以使用传统的寄存器,不管它们的长度是字节、字还是双字。在64位模式下,当然可以使用新增的64位寄存器,比如最后一条指令。