test eax, eax
效率是否cmp eax, 0
?在test eax, eax
不符合要求的情况下,是否有必要cmp eax, 0
?
答案 0 :(得分:25)
正如Zang MingJie在评论中已经说过,test eax,eax
几乎与cmp eax,0
完全相同,只是它短于cmp
,因为cmp
需要提供0
cmp
作为论据。请注意,节省的成本不是很大,因为第二个操作数会进行符号扩展以匹配第一个操作数的大小,因此它不一定需要整整4个字节来表示该值。
现在,您要问的是,是否还有其他差异。这是一个合理的问题,因为test
是一个算术运算,(它执行减法并丢弃结果),而Flags
是一个逻辑运算,(它执行按位AND并丢弃结果,)因此可以合理地怀疑他们可能会以不同方式修改Flags
注册。
事实证明,两条指令都以几乎相同的方式修改test
寄存器。两条指令都修改了标志寄存器的OF SF ZF AF PF和CF位。 cmp
指令总是清除OF和CF,但这也是cmp
对零的指令。唯一的另一个区别是test
指令将正确设置the obscure AF
flag,而cmp eax,0
指令则不会定义该标志的内容。但是在eax
的情况下,无论cmp eax,0
的值是什么,AF都会被清除,因此您无法从test eax,eax
中学到任何您不会从test eax,eax
中学到的内容。 {1}}。
因此,我的结论是,cmp eax,0
没有test eax,eax
会给你一些cmp eax,0
不会的东西,反之亦然。除了保存一个或两个指令代码之外,这两条指令对于任何实际或甚至不那么实用的目的而言似乎是完全可互换的。
使用BaseSensor
代替struct EdgeSensor //a mixin
{
void update(){}
void printStats() {}
};
struct TrendSensor //another mixin
{
void update(){}
void printStats() {}
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
void update() /*{ what goes in here??? }*/
void printStats() /*{ what goes in here??? }*/
};
表示您知道您的程序集。它还表明,您更倾向于使用一种稍微含糊不清且性能稍好的指令而不是直接易懂的指令。这种东西往往会从其他极客那里获得奖励积分,但在过去的几十年里,它在现实世界中没有任何实际用处。
答案 1 :(得分:1)
如上所述,在注释和接受的答案中,这些指令以这种方式使用时,几乎相同,但是为什么指令集中有两条相同的指令呢?
因为它们与不同的操作数一起使用会有所不同。
test same,same
可以与零进行比较,这只是2的补码和FLAGS如何工作的便利结果,使其成为有用的窥孔优化。
TEST指令对arg0和arg1的位对使用AND逻辑,并且可以检查是否设置了特定位,然后检查了FLAGS。 (丢弃整数结果)。就像cmp
从减法中设置FLAGS一样,同时丢弃整数结果。
HTML except来自英特尔vol.2 PDF manual
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给CMP指令设置CF(进位标志)和ZF(零标志),,如果两者相等(arg1 = = arg0),那么很明显结果将为零,并且ZF将被设置为1;如果arg0> arg1,那么将不会设置任何标志(对于ZF和CF仍为0);如果arg0 受影响的标志 根据结果设置CF,OF,SF,ZF,AF和PF标志。 Operation(CMP)
temp ← SRC1 − SignExtend(SRC2);
ModifyStatusFlags;
(* Modify status flags in the same manner as the SUB instruction*)