【问题标题】:Do 32 and 64 bit values share the same register space?32 位和 64 位值是否共享相同的寄存器空间?
【发布时间】:2017-04-26 00:25:11
【问题描述】:

如果我从 32 位寄存器中移动一个值,说:

    movq %rdx,%rax
    movl %edx,%eax

%rax 中存储的值会被破坏吗?

【问题讨论】:

  • 是的,虽然不是你想的那样。您也可以尝试一下。
  • 是的,当然。无论您是否使用 8/16/32/64 位模式寻址,它都是同一个寄存器。这是一个很好的图表:stackoverflow.com/a/228367/14955
  • @Jester “不是你想的那样。”请详细说明。
  • @Thilo 他已将rdx 移至rax,然后将edx 移至eax。如果不是因为 32 位操作将高位清零,这通常不会改变任何事情。

标签: assembly x86-64 att


【解决方案1】:

是的,

您的代码:

mov rax,rdx
mov eax,edx

将执行以下操作。

rax <= rdx
high 32 bits of rax <= 0, low 32 bits of rax <= edx.

分配一个 32 位寄存器将使该寄存器的较高部分归零。

对比:

mov rax,rdx   :  rax <= rdx
mov ax,dx     :  High 48 bits of rax is unchanged!, low 16 bits of rax <= dx

字节寄存器也是如此。

32 位将 64 位寄存器的上部分配为零的原因是它防止了部分寄存器更新,这会导致指令流水线中的延迟。

在 32 或 64 位模式下使用 16 位代码会导致以下情况出现延迟:

mov rax,-1       //1 cycle
mov ax,dx        //1 cycle
                 //stall, the values of rax-upper and ax need to be combined
mov r8,rax       //2 cycles

更好的选择是

mov rax,-1       //1 cycle
movzx eax,dx     //runs concurrent with previous instruction, 0 cycles
mov r8,rax       //1 cycle

//Total 2 cycles, twice as fast.

这段代码并不等同于上面的示例,但这就是重点。您应该尽可能避免部分寄存器更新。 另请注意,由于上述原因,movzx eax,dx 等同于 movzx rax,dx。在 x64 上,它短一个字节,因此是首选形式。

请注意,原则上我没有使用 ATT 语法

【讨论】:

  • “更好的选择”确实更快,但不等同于导致延迟的原始代码。 movzx 使初始的 mov 完全多余。此外,由于本答案前半部分给出的原因,movzx 可以更有效地写为movzx eax, dx
猜你喜欢
  • 1970-01-01
  • 2012-01-21
  • 2011-10-26
  • 1970-01-01
  • 2011-01-28
  • 2014-02-21
  • 2010-09-15
  • 1970-01-01
相关资源
最近更新 更多