"or eax,eax"和"test eax,eax"的区别



or eax,eaxtest eax,eax有什么区别?我见过不同的编译器产生相同的比较,就文档而言,他们做完全相同的事情,所以我想知道为什么他们不都使用test eax,eax。考虑一下,and eax,eax将以相同的方式设置标志,但我没有在freeppascal, delphi或msvc++中看到它。

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

编辑:
这个问题具体是关于test eax,eax, or eax,eaxand eax,eax具体案例的区别。这三种方法对寄存器、标志、操作码长度、延迟、吞吐量给出了完全相同的结果。然而,对于测试是否为0,如果不为0,或者如果有符号,一些编译器将使用test eax,eax,而一些使用or eax,eax,我想知道为什么他们不都使用test eax,eax,因为它使代码非常清晰。

Edit2:
作为参考,我在家里,只有和旧的msvc++和Delphi在这里,但测试一个变量,如果零,msvc++做test eax,eax,而Delphi做or eax,eax

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

test可以是一个更好的指令选择,因为像微op融合这样的事情。因此,除非必须重复计算,否则test通常是首选。cmp/sub也一样。

在英特尔的文档中搜索"fusion",你应该可以找到详细信息。

确定test eax, eax之后eax的内容与指令之前相同的电路比or eax, eax得出该结论所需的电路更简单。因此,test是更好的选择。

一些编译器可能会在没有任何区别的时候生成or(在乱序执行之前),但它会对现在的一些乱序处理器产生影响(然而其他OOO处理器将如此复杂,以至于它们将or eax, eax识别为真正等同于test eax, eax)。

我找不到证明一些现代处理器实际上能够推断or reg, reg不修改reg的参考,但这里有一个答案声称这是xchg reg, reg的情况。

只是为了重申一点@gsg所表示的内容,并对其进行一点补充,TEST指令对两个操作数进行按位逻辑比较(本质上是在内部按位进行and,但不存储结果),并根据该操作的结果设置处理器标志。OR指令对源和目标进行逻辑或,将结果存储在目标中,并根据结果设置处理器标志。它们都以相同的方式影响处理器标志。所以当操作数相同时,行为是相同的。旗子没有区别。然而,当操作数不同时,它们的行为就会大不相同。您还可以使用and eax,eax测试零,这也同样影响标志。

最新更新