为什么会生成如此奇怪的代码?

时间:2013-12-09 09:09:56

标签: assembly x86 g++

考虑一段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

1 个答案:

答案 0 :(得分:6)

我认为这与在C和C ++中处理bool的方式有所不同。在您的代码中,if(!a)首先将a转换为booltest 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