< p >“or eax,eax”和“test eax,eax”的区别是什么?我看到不同的编译器在相同的比较中产生了两种不同的结果,就文档而言它们完全一样,所以我想知道为什么它们不都使用“test eax,eax”。考虑到“and eax,eax”会以与任何一个相同的方式设置标志,但我在freepascal,delphi或msVC ++中都没有看到它。
我在Delphi中编译了一些asm块并查看了汇编源代码,发现所有3种形式的操作码长度完全相同,我还检查了英特尔性能PDF,它说它们具有相同的延迟和吞吐量。
编辑:
问题特别涉及到“test eax,eax”,“or eax,eax”和“and eax,eax”之间的区别。对于寄存器、标志、操作码长度、延迟和吞吐量,所有3个都给出完全相同的结果。然而,为了测试是否为0,如果不为零或者如果带符号,一些编译器将使用“test eax,eax”,而一些编译器将使用“or eax,eax”,我想知道为什么他们不都使用“test eax,eax”,因为它使代码稍微更清晰一些。
编辑2:
作为参考,我在家里只有旧版的msvc ++和Delphi,在测试变量是否为零时,msvc ++使用“test eax,eax”,而Delphi使用“or eax,eax”。
test
更好,包括一些没有在任何地方提到的原因。现在甚至考虑使用or same,same
的唯一原因是针对P6系列CPU,在这些CPU上,将寄存器与自身重写可以使其在乱序核心中保持“活动状态”,可能避免/减少后续指令读取相同寄存器时的寄存器读取停顿。但是,测试/ jcc的宏融合通常会超过这一点,除非实验显示特定热点受益。但也许正是这个原因,而不仅仅是惯性,是Delphi使用or
的原因。 - Peter Cordesand
比or
更好(或者至少不会更差),因为它可以与Sandybridge系列上的jcc进行宏融合。但在大多数情况下,它仍然比更多的CPU上的test
要差,并且仍然会在后续指令读取寄存器之前增加一个周期的延迟。如果您想避免P6上的寄存器读取停顿并仍然在SnB上获得宏融合,请使用and
。如果您的代码可以在包括Sandybridge系列的CPU上运行,则or
/jcc
始终是次优的。 - Peter Cordes