我有一些未知的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行,因为流水线的原因,它们可能在这里,IMHO与EAX没有任何关系。
但是,我不明白为什么我要先清除AL,然后再清除EAX的其余部分。结果将永远是EAX = 0,所以这也可能是
xor eax, eax而不是。这段代码的优点或“优化”是什么?
一些背景信息:
稍后我会得到源代码。这是一个简短的C++控制台演示程序,可能只有20行代码,所以我不会称之为“复杂”代码。IDA在该程序中显示了一个循环,但不是围绕这个部分。Stud_PE签名扫描没有发现任何东西,但很可能是Visual 2013或2015编译器。
发布于 2017-11-08 21:23:22
在大多数CPU上,xor al,al已经比xor eax,eax慢了。例如rax。在AMD CPU或Atom/Silvermont上也同样糟糕。(嗯,也许不是同样的原因,因为AMD没有在问题/重命名时消除xor eax,eax,但是它仍然有一个错误的依赖项,它可以序列化新的依赖链,不管最后使用的是什么)。
在将al与寄存器的其他部分分别重命名的CPU上(英特尔预科特迪瓦桥),xor al,al仍然可能被识别为as a zeroing idiom,但是除非您积极地想要保留寄存器的上字节,否则实现al零的最好方法是xor eax,eax。
在此基础上做movzx只会让事情变得更糟。
我猜你的编译器不知怎么搞错了,决定它需要一个1字节零,但后来意识到它需要提升到32位。xor设置标志,因此它不能在cmp之后设置xor-zero,而且它也没有注意到它可能在cmp之前只设置了xor零的eax。
要么是something like Jester's suggestion,要么是movzx是分支目标。即使是这样,xor eax,eax仍然会更好,因为在这个代码路径上,零扩展到eax是无条件的。
我很好奇是什么编译器从什么来源产生的。
https://stackoverflow.com/questions/47189701
复制相似问题