Assembly 为什么会产生如此奇怪的代码? 考虑一段C++代码: int main() { volatile int a=0; if(!a) ++a; }

Assembly 为什么会产生如此奇怪的代码? 考虑一段C++代码: int main() { volatile int a=0; if(!a) ++a; },assembly,x86,g++,Assembly,X86,G++,我在amd64系统上用 使用命令g++test.cpp-S-o test.S-masm=intel获得以下代码: ... 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

我在amd64系统上用 使用命令
g++test.cpp-S-o test.S-masm=intel
获得以下代码:

...
    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
后再次检查结果?为什么它不做<代码>测试EAX、EAX\N JNE、L2</代码>?/P> < P>我认为它与C(C++)中的代码< BoOL < /C> >的处理方式不同。在代码中,
if(!a)
首先将
a
转换为
bool
(这就是
测试eax,eax;sete al
所做的),然后测试该布尔值(在
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
。注意,<>代码> A/C++ >从来没有涉及过,所以这意味着在测试它为非零之前,该值永远不会被转换为一个字节<代码> Boo.<代码>。无用的指令将消失。@NilsPipenbrinck我知道优化。问题是为什么会这样,而不是如何修复。