3.4.1 一个意外的行为
我们一般会认为 eax,rax,ax 等等,是同一个物理寄存器的不同部分。从观察过程中得到的结果一般是支撑得住这个假想的,直到我们往一个 64 位寄存器里写入一个 32 位的值的时候,事情才变得不太对劲了。我们来看看列表 3-3 中的代码示例:
Listing 3-3.The Land of Registry Wonders risc_cisc.asm
mov rax, 0x1122334455667788 ; rax = 0x1122334455667788
mov eax, 0x42 ; !rax = 0x00 00 00 00 00 00 00 42
; why not rax = 0x1122334400000042 ??
mov rax, 0x1122334455667788 ; rax = 0x1122334455667788
mov ax, 0x9999 ; rax = 0x1111222233339999, as expected
; this works as expected
mov rax, 0x1122334455667788 ; rax = 0x1122334455667788
xor eax, eax ; rax = 0x0000000000000000
; why not rax = 0x1122334400000000?
可以看到,写 8 位或者 16 位都是可以让其余的部分保持不变的。只有在写 32 位时,会把高位部分全都填上标识位!
实际上程序员脑子中熟悉的处理器和实际的处理器内部的运作方式是大不相同的。实际上,寄存器 rax,eax 和所有其它的寄存器并不是一种存在的固定物理实体。
为了解释这种不一致性,我们需要先来详细地说明一下两种指令集:CISC 和 RISC。