【发布时间】:2012-06-25 23:43:27
【问题描述】:
在x86-64 Tour of Intel Manuals,我读到了
也许最令人惊讶的事实是,诸如
MOV EAX, EBX之类的指令会自动将RAX寄存器的高32 位归零。
同一来源引用的英特尔文档(3.4.1.1 64 位模式中的通用寄存器在手册基本架构中)告诉我们:
- 64 位操作数在目标通用寄存器中生成 64 位结果。
- 32 位操作数生成 32 位结果,在目标通用寄存器中进行零扩展为 64 位结果。
- 8 位和 16 位操作数生成 8 位或 16 位结果。目标通用寄存器的高 56 位或 48 位(分别)不会被操作修改。如果 8 位或 16 位运算的结果用于 64 位地址计算,请将寄存器显式符号扩展为完整的 64 位。
在x86-32和x86-64汇编中,16位指令如
mov ax, bx
不要表现出这种eax的高位字归零的“奇怪”行为。
因此:引入这种行为的原因是什么?乍一看似乎不合逻辑(但原因可能是我习惯了 x86-32 汇编的怪癖)。
【问题讨论】:
-
如果您在 Google 上搜索“部分寄存器停顿”,您会发现很多关于他们(几乎可以肯定)试图避免的问题的信息。
-
不仅仅是“大多数”。 AFAIK,带有
r32目标操作数的 all 指令将高位 32 归零,而不是合并。例如,一些汇编程序会将pmovmskb r64, xmm替换为pmovmskb r32, xmm,从而节省了REX,因为64 位目标版本的行为相同。尽管Operation section of the manual 分别列出了 32/64 位 dest 和 64/128/256b 源的所有 6 种组合,但 r32 形式的隐式零扩展复制了 r64 形式的显式零扩展。我对硬件实现很好奇... -
@HansPassant,循环引用开始。
-
相关:
xor eax,eaxorxor r8d,r8dis the best way to zero RAX or R8(为 RAX 保存 REX 前缀,并且在 Silvermont 上甚至没有专门处理 64 位 XOR)。相关:How exactly do partial registers on Haswell/Skylake perform? Writing AL seems to have a false dependency on RAX, and AH is inconsistent
标签: assembly x86 x86-64 cpu-registers zero-extension