我正在将C代码转换成x86汇编,其中有一行:
if (bitmask & bit)
我使用gcc编译器生成了汇编代码,其中这一部分内容如下:
andl %edx, %eax
testl %eax, %eax
je else
(EAX是位,EDX是掩码)
andl
指令是否必要?还是将其修改为以下形式的testl
也能起到同样的作用:
testl %edx, %eax
je else
?
testl
或者andl
,但不是两个都需要。andl %edx, %eax
将按位与操作的结果放入%eax中。
现在让我们看一下对目标(第一个)和源(第二个)操作数执行按位与操作,并将结果存储在目标操作数位置。源操作数可以是立即数、寄存器或内存位置;目标操作数可以是寄存器或内存位置。(但是,一个指令中不能使用两个内存操作数。)如果第一个和第二个操作数的每个对应位都为1,则结果的每个位都设置为1;否则,它被设置为0。
OF和CF标志被清除;根据结果设置SF、ZF和PF标志。AF标志的状态未定义。
testl
(PDF文档的第121页和122页)。testl %eax, %eax
testl
也在特定行执行与您刚刚执行的相同的 and 操作。
具体来说,testl
:
计算第一个操作数(源操作数1)和第二个操作数(源操作数2)的按位逻辑 AND,并根据结果设置SF、ZF和PF标志。然后丢弃结果。
在64位模式下,使用REX.R形式的REX前缀可以访问额外的寄存器(R8-R15)。使用REX.W形式的REX前缀将操作提升到64位。有关编码数据和限制,请参见本节开头的摘要表。
http://www.felixcloutier.com/x86/TEST.html
在这种情况下,两个操作数是相同的,即andl
的结果。如果操作数为0,则将其与自身进行逻辑与运算的结果为0。将任何其他值与自身进行逻辑与运算会产生非零值。
总结
我不确定为什么GCC会生成andl
和testl
指令。我没有看到需要同时使用两者的场景,因为testl
执行了and操作,并且两者都设置了je
指令所需的ZF。andl
指令根据结果设置Z标志。 - Raymond Chenandl
,即使在任何情况下都不需要它?如果从来没有可能出现副作用,那么即使没有启用任何优化,它也不会被发出。 - Eric J.AND
是用来表示表达式的,而TESTL
是用来测试if
条件的。进行优化后,可以将它们折叠为单个操作。但你没有回答问题。只使用TESTL
就足够了,正如OP所假设的那样。 - too honest for this site
testl
,而他的困惑似乎是andl
是否设置ZF,或者他不知道je
需要ZF适当设置。 - Eric J.