test eax, eax
是否比cmp eax, 0
更有效率?在cmp eax, 0
不符合要求的情况下,是否需要test eax, eax
?
正如臧明杰在评论中已经说过的,test eax, eax
几乎与cmp eax, 0
相同,除了它比cmp
短,因为对于cmp
,你必须提供0
作为参数。注意,节省的空间并不是很大,因为第二个操作数进行了符号扩展,以匹配第一个操作数的大小,所以不一定需要整整4个字节来表示这个0。
现在,你要问的是是否还有其他的区别。这是一个合理的问题,因为cmp
是一个算术运算(它执行减法并丢弃结果),而test
是一个逻辑运算(它执行按位与运算并丢弃结果),所以人们可以合理地怀疑它们可能以不同的方式修改Flags
寄存器。
结果是,两个指令以几乎相同的方式修改Flags
寄存器。两个指令都修改标志寄存器的OF、SF、ZF、AF、PF和CF位。test
指令总是清除OF和CF,但这也是cmp
对0所做的。唯一的另一个区别是cmp
指令将正确设置模糊的AF
标志,而test
指令使该标志的内容未定义。但是在cmp eax,0
的情况下,无论eax
的值是多少,AF都会被清除,所以你可以从cmp eax, 0
中学到的东西,你不能从test eax, eax
中学到。
因此,我可以得出结论,没有test eax, eax
会给你cmp eax, 0
不会给你的东西的情况,反之亦然。除了节省一两个字节的指令代码外,这两条指令似乎完全可以互换用于任何实际目的,甚至不太实际的目的。
使用test eax, eax
而不是cmp eax, 0
表明您了解您的汇编。它还表明,与直接易懂的指令相比,您更喜欢略显晦涩但性能稍好一些的指令。这是一种倾向于从其他极客那里获得加分的东西,但在过去几十年左右的时间里,它在现实世界中没有任何实际用途。
# 的区别(理论)
正如上面在评论和接受的回答中所述,当以这种方式使用时,这些指令几乎相同,但是如果它们是相同的,为什么指令集中有两个指令呢?
因为它们用于不同的操作数是不同的。事实上,test same,same
作为0的比较,只是2的补码和FLAGS如何工作的一个方便的结果,使其成为一个有用的窥视孔优化。
TEST指令在arg0和arg1的位对上使用AND逻辑,并且可以检查特定位是否设置,然后相应地设置FLAGS。(整数结果被丢弃)。就像cmp
从减法中设置FLAGS,同时丢弃整数结果。
# 操作(测试)
HTML除了来自Intel的vol.2 PDF手册
TEMP ← SRC1 **AND** SRC2; SF ← MSB(TEMP); IF TEMP=0 THEN ZF ← 1; ELSE ZF ← 0; FI: PF ← BitwiseXNOR(TEMP[0:7]); CF ← 0; OF ← 0; (* AF is undefined *)
标记影响
OF和CF标志设置为0。设置SF、ZF和PF标志根据结果(参见上面的"操作"部分)。的AF标志的状态未定义
(TEST操作将标志CF和OF设置为零。SF被设置为AND运算结果的最高有效位。如果结果为0,则ZF设置为1,否则设置为0。
虽然CMP指令使用SUB指令并从arg0中减去arg1,并将根据给定的args设置CF(进位标志)和ZF(零标志)到CMP指令,如果两者相等(arg1==arg0),那么很明显结果将为零,ZF将被设置为1,如果arg0>arg1则不设置任何标志(对于ZF和CF保持0),如果arg0 <arg1则ZF将保持0,因为它们不相等,但CF将被设置。>
# 操作(CMP)
temp ← SRC1 − SignExtend(SRC2); ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)
标记影响
根据结果设置CF、OF、SF、ZF、AF和PF标志。