Assembly 为什么会产生如此奇怪的代码? 考虑一段C++代码: int main() { volatile int a=0; if(!a) ++a; }
我在amd64系统上用 使用命令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
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我知道优化。问题是为什么会这样,而不是如何修复。