or eax,eax
和test eax,eax
有什么区别?我见过不同的编译器产生相同的比较,就文档而言,他们做完全相同的事情,所以我想知道为什么他们不都使用test eax,eax
。考虑一下,and eax,eax
将以相同的方式设置标志,但我没有在freeppascal, delphi或msvc++中看到它。
我确实在delphi中编译了一些asm块,并检查了汇编程序源,所有3种形式的操作码长度完全相同,并且还检查了英特尔性能PDF,它说它们具有相同的延迟和吞吐量。
编辑:
这个问题具体是关于test eax,eax
, or eax,eax
和and eax,eax
具体案例的区别。这三种方法对寄存器、标志、操作码长度、延迟、吞吐量给出了完全相同的结果。然而,对于测试是否为0,如果不为0,或者如果有符号,一些编译器将使用test eax,eax
,而一些使用or eax,eax
,我想知道为什么他们不都使用test eax,eax
,因为它使代码非常清晰。
Edit2:
作为参考,我在家里,只有和旧的msvc++和Delphi在这里,但测试一个变量,如果零,msvc++做test eax,eax
,而Delphi做or eax,eax
。
一般来说,test
和and
之间的唯一区别是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
测试零,这也同样影响标志。