考虑一段C ++代码:
int main()
{
volatile int a=0;
if(!a)
++a;
}
我在amd64系统上编译它
使用命令g++ test.cpp -S -o test.S -masm=intel
的g ++(Ubuntu 4.8.1-2ubuntu1~12.04)并获取以下代码:
...
mov eax, DWORD PTR [ebp-4]
test eax, eax
sete al
test al, al
je .L2
mov eax, DWORD PTR [ebp-4] ; don't use result of sete
add eax, 1
mov DWORD PTR [ebp-4], eax
.L2:
mov eax, 0 ; also drop result of sete
...
这段代码让我很惊讶。起初我认为它与64位模式有关。但是当我尝试使用-m32
进行编译时,这个位保持不变。
为什么检查eax
为零,然后在将al
设置为ZF
后再次重新检查结果?为什么不只是test eax,eax\n jne .L2
?
答案 0 :(得分:6)
我认为这与在C和C ++中处理bool
的方式有所不同。在您的代码中,if(!a)
首先将a
转换为bool
(test eax, eax; sete al
执行的内容),然后然后测试对于true / false,该布尔值(在al
中)。
如果您重命名为.c
并使用gcc
编译相同的代码,则会生成预期的代码
mov DWORD PTR [rbp-4], 0
mov eax, DWORD PTR [rbp-4]
test eax, eax
jne .L3
mov eax, DWORD PTR [rbp-4]
add eax, 1
mov DWORD PTR [rbp-4], eax
.L3:
在C中,似乎没有中间转换为bool
的情况下发生积分变量的布尔测试。请注意,al
永远不会涉及,因此这意味着该值永远不会被转换为"在将其测试为非零之前,将其设为一个字节bool
。