为什么gcc会生成冗长的汇编代码?

4

我希望你能帮忙翻译GCC生成的汇编代码(使用-S选项)。由于我对汇编语言很陌生,所以我的问题可能比较基础。但我还是希望有人能够回答:

假设我有以下C代码:

main(){

    int x = 15; 

    int y = 6;

    int z = x - y;


    return 0;
}

如果我们查看汇编代码(尤其是与 int z = x - y 对应的部分),我们会看到:
主函数:
...
subl    $16, %esp
movl    $15, -4(%ebp)
movl    $6, -8(%ebp)
movl    -8(%ebp), %eax
movl    -4(%ebp), %edx
movl    %edx, %ecx
subl    %eax, %ecx
movl    %ecx, %eax
movl    %eax, -12(%ebp)
...

为什么GCC不生成类似于这样的内容,少复制一些东西呢?
主函数:
...
movl    $15, -4(%ebp)
movl    $6, -8(%ebp)
movl    -8(%ebp), %edx          
movl    -4(%ebp), %eax          
subl    %edx, %eax              
movl    %eax, -12(%ebp)
...

P.S.

Linux zion-5 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:10:02 UTC 2010 i686 GNU/Linux gcc版本为4.4.3(Ubuntu 4.4.3-4ubuntu5)


12
打开优化。 - Mysticial
1
使用-O2编译选项,我发现赋值和减法也会消失,因为它们是死代码 - ArjunShankar
5
我刚刚检查了一下。-O1 本身就会移除所有内容。生成的代码只相当于 return 0; - ArjunShankar
1个回答

8
首先,就像Mysticial所评论的那样,您应该开启一些优化。尝试将-O2(或-O3,或只是-O1)传递给gcc。如果您想更好地理解生成的汇编代码,请同时传递-fverbose-asm。如果您想了解代码为什么会被生成(或未被生成),请学习GCC内部知识(也许还要传递-fdump-tree-all-fdump-rtl-all,这会产生大量的内部转储文件)。
一些有关MELT(MELT是一种特定领域语言,用于扩展GCC)的幻灯片可能会有所帮助,并提供其他参考资料。
当要求时,您可能会对GCC可以提供的优化数量感到惊讶。默认情况下,GCC不进行优化。有一些优化需要您明确要求(甚至在-O3中也没有进行)。
最近的GCC版本可能比旧版本进行更多的优化。2021年当前的GCC版本为GCC 11
附:我不再从事MELT的工作(在2017年放弃了它)。2021年,还可以看看BismonRefPerSysFrama-C

我还建议除了-fdump-tree-all之外,使用-fdump-rtl-all,它会将汇编输出与内部gcc表示进行注释。 - flolo
2
这让我想起了我曾经为计算向量范数编写的某个函数。当看到gcc如何进行优化时,我得到了以下结果(使用常量输入):-O1:函数内联,-O2:循环也被展开,-O3:常量向量的范数在代码中静态地存在,根本不需要计算。(可能混淆了-O1和-O2) - Jonas Schäfer
MELT网站目前看起来像是垃圾邮件网站,URL改变了吗? - qwr
已更正。我添加了一些存档的链接。 - Basile Starynkevitch
1
@JonasSchäfer:如果你想看看gcc如何计算某些东西,不要给它一个常量输入。只需编写一个接受参数并返回值的函数即可。请参见如何从GCC/clang汇编输出中删除“噪音”?。如果您想查看汇编代码而不是运行它,则不需要main - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接