最佳答案
正如广泛宣传的那样,现代的 x86 _ 64处理器有64位寄存器,可以作为32位寄存器、16位寄存器甚至8位寄存器以向后兼容的方式使用,例如:
0x1122334455667788
================ rax (64 bits)
======== eax (32 bits)
==== ax (16 bits)
== ah (8 bits)
== al (8 bits)
这种方案可按字面意思理解,即只能使用指定名称进入登记册的某一部分,以便阅读或书写,这是非常合乎逻辑的。事实上,对于32位以下的所有内容都是如此:
mov eax, 0x11112222 ; eax = 0x11112222
mov ax, 0x3333 ; eax = 0x11113333 (works, only low 16 bits changed)
mov al, 0x44 ; eax = 0x11113344 (works, only low 8 bits changed)
mov ah, 0x55 ; eax = 0x11115544 (works, only high 8 bits changed)
xor ah, ah ; eax = 0x11110044 (works, only high 8 bits cleared)
mov eax, 0x11112222 ; eax = 0x11112222
xor al, al ; eax = 0x11112200 (works, only low 8 bits cleared)
mov eax, 0x11112222 ; eax = 0x11112222
xor ax, ax ; eax = 0x11110000 (works, only low 16 bits cleared)
然而,一旦我们开始使用64位的东西,事情似乎就变得相当尴尬了:
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
mov eax, 0x55556666 ; actual: rax = 0x0000000055556666
; expected: rax = 0x1111222255556666
; upper 32 bits seem to be lost!
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
mov ax, 0x7777 ; rax = 0x1111222233337777 (works!)
mov rax, 0x1111222233334444 ; rax = 0x1111222233334444
xor eax, eax ; actual: rax = 0x0000000000000000
; expected: rax = 0x1111222200000000
; again, it wiped whole register
在我看来,这种行为是非常荒谬和不合逻辑的。它看起来像试图写任何东西到 eax通过任何手段导致擦除高32位的 rax寄存器。
我有两个问题:
我相信这种尴尬的行为一定被记录在某个地方,但是我似乎找不到任何详细的解释(关于64位的32位寄存器究竟是如何被清除的)。写入 eax总是擦除 rax,我说的对吗? 或者是更复杂的东西?它是否适用于所有64位寄存器,还是有一些例外?
非常相关的问题提到了同样的行为,但是,唉,同样没有对文档的确切引用。
换句话说,我想要一个指定这种行为的文档链接。
是只有我这么觉得,还是这整件事看起来真的很奇怪和不合逻辑(比如,一个行为一个行为,一个行为一个行为) ?也许我在这里漏掉了一些关键点,为什么要这样实施呢?
如能解释一下“为什么”我将不胜感激。