XOR AL,AL + MOVZX EAX,AL优于XOR EAX,EAX的任何优势?

时间:2017-11-08 21:06:22

标签: c++ assembly x86

我有一些在Release版本中编译的未知C ++代码,因此它已经过优化。我挣扎的一点是:

xor     al, al
add     esp, 8
cmp     byte ptr [ebp+userinput], 31h
movzx   eax, al

这是我的理解:

xor     al, al    ; set eax to 0x??????00 (clear last byte)
add     esp, 8    ; for some unclear reason, set the stack pointer higher
cmp     byte ptr [ebp+userinput], 31h ; set zero flag if user input was "1"
movzx   eax, al   ; set eax to AL and extend with zeros, so eax = 0x000000??

我不关心第2行和第3行。由于流水线原因,他们可能会按此顺序出现,而恕我直言与EAX无关。

但是,我不明白为什么我会首先清除AL,以便稍后清除EAX的其余部分。结果将是恕我直言EAX = 0,所以这也可能是

xor eax, eax

代替。优势是什么?"优化"那段代码?

一些背景信息:

稍后我会得到源代码。它是一个简短的C ++控制台演示程序,可能只有20行代码,所以没有什么我称之为"复杂"码。 IDA在该程序中显示单个循环,但不包括此部分。 Stud_PE签名扫描没有找到任何内容,但可能是它的Visual Studio 2013或2015编译器。

1 个答案:

答案 0 :(得分:3)

在大多数CPU上,

xor al,al已经慢于xor eax,eax。例如on Haswell/Skylake it needs an ALU uop and doesn't break the dependency on the old value of eax/rax。它在AMD CPU或Atom / Silvermont上同样糟糕。 (好吧,也许不一样,因为AMD没有消除xor eax,eax的问题/重命名,但它仍然有一个错误的依赖,它可以使用最后使用的eax序列化新的依赖链。

在将al与寄存器的其余部分(Intel pre-IvyBridge)分开重命名的CPU上,xor al,al可能仍会被识别as a zeroing idiom,但除非您主动要保留寄存器的高位字节,归零al的最佳方法是xor eax,eax

在此基础上执行movzx会让情况变得更糟。

我猜你的编译器有点混淆并决定它需要一个1字节的零,但后来意识到它需要将它提升到32位。 xor设置了标记,因此在<{em> xor之后无法cmp - 零,并且它没有注意到它可能只有xor-zeroed {{ 1}}在eax之前。

要么是something like Jester's suggestion,要么cmp是分支目标。即使是这种情况,movzx仍然会更好,因为在此代码路径上无条件地遵循零扩展到eax。

我很好奇编译器从什么来源产生了这个。