考虑一段C++代码:
int main()
{
volatile int a=0;
if(!a)
++a;
}
Run Code Online (Sandbox Code Playgroud)
我使用g ++(Ubuntu 4.8.1-2ubuntu1~12.04)使用命令在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
...
Run Code Online (Sandbox Code Playgroud)
这段代码真让我感到惊讶.起初我认为它与64位模式有关.但是当我尝试编译时-m32,这个位保持不变.
为什么它检查eax的是零,然后设置后重新检查结果再一次al给ZF?为什么不test eax,eax\n jne .L2呢?
我认为它与boolC和C++中的处理方式有关.在你的代码中,第if(!a)一个转换a为a bool(这就是它的test eax, eax; sete al作用),然后测试boolean(in al)的true/false.
如果重命名为.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:
Run Code Online (Sandbox Code Playgroud)
在C中,似乎没有中间转换的积分变量的布尔测试bool.请注意,al它从不涉及,因此这意味着在将值bool测试为非零之前,该值永远不会"转换"为一个字节.