“或eax,eax”和“test eax,eax”之间的区别

时间:2014-05-16 03:05:09

标签: assembly x86 micro-optimization

or eax,eaxtest eax,eax之间有什么区别?我已经看到不同的编译器生成两者用于相同的比较,并且就文档而言它们做的完全相同,所以我想知道为什么他们并不都使用test eax,eax。考虑它and eax,eax会以相同的方式设置标志,但我没有在freepascal,delphi或msVC ++中看到它。

我确实在delphi中编译了一些asm块并检查了汇编源,并且所有3种形式在操作码中的长度完全相同,并且还检查了英特尔性能PDF并且它说它们具有相同的延迟和吞吐量。

编辑:
问题是具体案例test eax,eaxor eax,eaxand eax,eax之间的区别。所有3给出完全相同的寄存器,标志,操作码长度,延迟,吞吐量的结果。然而,如果测试0,如果不是零,或者如果签名,一些编译器将使用test eax,eax而一些使用or eax,eax,我想知道他们为什么不是全部使用test eax,eax它使代码更加清晰。

EDIT2:
作为参考,我在家里只有较旧的msvc ++和Delphi,但测试变量为零,msvc ++执行test eax,eax,而Delphi执行or eax,eax

3 个答案:

答案 0 :(得分:6)

通常,testand之间的唯一区别是test <reg>, <reg>不会修改其操作数。基本上test应用and操作,丢弃结果的非标志部分。如果操作数相同,则结果将相同(or)。

由于微操作融合之类的东西,

test可以成为优秀的教学选择。因此,test通常是首选,除非必须重复计算。同样适用于cmp / sub

搜索英特尔的“融合”文档,您应该找到详细信息。

答案 1 :(得分:2)

只是重复一点,并添加一点@gsg指示的内容,TEST指令对两个操作数进行按位逻辑比较(本质上是按位内部进行AND运算,但不存储结果),并根据到该操作的结果。 OR指令执行源与目标的逻辑OR,将结果存储在目标中,并根据结果设置处理器标志。它们都以相同的方式影响处理器标志。因此,当操作数相同时,行为是相同的。旗帜没有区别。但是,当操作数不同时,它们的行为就会大不相同。您还可以使用and eax,eax测试零,这也会同样影响标记。

答案 2 :(得分:2)

确定eax之后的test eax, eax的内容与指令之前相同的电路比到达or eax, eax的结论所需的电路更简单。出于这个原因,test更好。

某些编译器可能在没有任何差异时(在无序执行之前)生成or,但它现在会对某些无序处理器产生影响(而但其他OOO处理器将非常复杂,以至于它们会将or eax, eax视为真正等同于test eax, eax)。

我无法找到一个参考证明某些现代处理器实际上能够推断or reg, reg不会修改reg,但是here is答案声称是这种情况xchg reg, reg