如果我从32位寄存器移动一个值,请说:
for _ in 0..<1000 {
value -= 1
}
存储在%rax中的值会被破坏吗?
答案 0 :(得分:2)
是,
您的代码:
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语法,原则上