TEST指令和AND指令 x86

4

我正在将C代码转换成x86汇编,其中有一行:

if (bitmask & bit)

我使用gcc编译器生成了汇编代码,其中这一部分内容如下:

andl %edx, %eax
testl %eax, %eax
je else

(EAX是位,EDX是掩码)

andl指令是否必要?还是将其修改为以下形式的testl也能起到同样的作用:

testl %edx, %eax
je else

?


2
请提供一个最小化、完整、可复制的示例(MCVE)。根据所提供的信息,无法回答这个问题。您使用了哪个优化级别? - too honest for this site
2
@Olaf:这与优化无关。OP想知道是否需要testl,而他的困惑似乎是andl是否设置ZF,或者他不知道je需要ZF适当设置。 - Eric J.
2
@EricJ。我猜原帖的真正问题是“为什么GCC生成了这个显然不必要的指令?” - Ross Ridge
@EricJ 如果没有必要的话,我们应该删除 [gcc] 标签和 C 代码,并严格限制为汇编代码,对吧? - Evan Carroll
@EvanCarroll:这不是我的问题,但我认为上下文与问题相关,并且个人不会将其删除。 - Eric J.
1个回答

4
你只需要testl或者andl,但不是两个都需要。
让我们来看一下GCC生成的代码。
代码:
andl %edx, %eax

将按位与操作的结果放入%eax中。

对目标(第一个)和源(第二个)操作数执行按位与操作,并将结果存储在目标操作数位置。源操作数可以是立即数、寄存器或内存位置;目标操作数可以是寄存器或内存位置。(但是,一个指令中不能使用两个内存操作数。)如果第一个和第二个操作数的每个对应位都为1,则结果的每个位都设置为1;否则,它被设置为0。

OF和CF标志被清除;根据结果设置SF、ZF和PF标志。AF标志的状态未定义。

http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

现在让我们看一下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会生成andltestl指令。我没有看到需要同时使用两者的场景,因为testl执行了and操作,并且两者都设置了je指令所需的ZF。

3
andl指令根据结果设置Z标志。 - Raymond Chen
2
官方英特尔指令集参考手册中写道:OFCF标志被清除;SFZFPF标志根据结果设置。AF标志的状态是未定义的。换句话说,testand完全等价,结果被丢弃。 - Jester
@Jester:你有没有想过为什么GCC会产生andl,即使在任何情况下都不需要它?如果从来没有可能出现副作用,那么即使没有启用任何优化,它也不会被发出。 - Eric J.
5
我认为这段代码没有进行优化,所以AND是用来表示表达式的,而TESTL是用来测试if条件的。进行优化后,可以将它们折叠为单个操作。但你没有回答问题。只使用TESTL就足够了,正如OP所假设的那样。 - too honest for this site
我不是x86汇编专家(太难读,设计不好)。请参阅@Jester发布的链接第3-55页。那里清楚地说明“AND”指令设置标志(不确定“ANDL”是什么,在手册中没有给出 - 我假设这是语法变化)。请注意,这是大多数体系结构上ALU指令的正常行为。而“TEST”指令的行为相同,但不改变目标。 - too honest for this site
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接