当前位置: 首页 > 知识库问答 >
问题:

为什么gcc会生成详细的汇编代码?[副本]

令狐高洁
2023-03-14

我有一个关于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)
...

为什么海湾合作委员会不生成这样的东西,这样就不会复制东西。

主要内容:

...
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-52.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)

共有1个答案

马飞
2023-03-14

首先,正如Mystical所评论的,您应该启用一些优化。尝试将-O2(或-O3,或只是-O1)传递到gcc。如果您想进一步了解生成的汇编代码,请同时传递-fverbose asm。如果您想了解生成(或不生成)代码的原因,请学习GCC内部(可能还需要传递-fdump tree all-fdump rtl all,它们会生成大量内部转储文件)。

MELT上的一些幻灯片(MELT是扩展GCC的领域特定语言)可能会有所帮助,并提供其他参考。

当你被要求时,你可能会惊讶于GCC能给你的优化量。默认情况下,GCC不优化。有一些您应该明确要求的优化(甚至在-O3中也不做)。

GCC的最新版本可能比旧版本优化更多。目前的GCC版本在2021是GCC 11。

另外,我不再在MELT上工作(2017年放弃)。在2021,也见BISMON,RefSysS,FRAMA-C。

 类似资料:
  • 让我们用一个简单的C代码来设置寄存器: 当我使用1级优化为ARM(ARM none eabi gcc)编译此代码时,汇编代码如下所示: 看起来地址111111被解析到最接近的4K边界(110592)并移动到r3,然后通过将519添加到110592 (=111111)来存储值4096(0x1000)。为什么会这样? 在x86中,组装非常简单:

  • 我正在为64位mips机器使用gcc编译器。我注意到生成的一段汇编代码很有趣。下面是详细信息: 通常,bnez将立即跳到0xb0。但在0xb0之后的块中,我确信程序必须使用a1作为参数。但是我们可以看到,在0xb0之后,a1从未出现在块中。 但是a1在0x58中使用,就在bnez(0x54)之后。 那么0x54和0x58指令有可能同时执行吗?超标量处理器通过同时将多条指令分派到处理器上的冗余功能单

  • 例子 #include <stdio.h> int main(void) { int i; for (i = 0; i < 10; i++) printf("%d ", i); putchar ('\n'); return 0; } 技巧 使用-fverbose-asm选项就可以生成带有详细信息的汇编文件: $ gcc -S -fverbose-asm foo.c

  • 我在Mac OS X上使用Java8编译了一个简单的Java文件到assembly。这是test.Java:

  • 该程序应该使用int 0x10在ASCII中打印一个具有给定字符的金字塔,3行的预期结果(下面代码中使用的数量)将是: A. a a a a a 要编译和运行代码,我使用nasm编译它,然后使用qemu进行仿真: 然而,程序get无法打印所有ASCII值。此外,如果有任何针对nasm代码的调试器,可以让您逐行运行,允许您检查寄存器值,这对学习也很有帮助。

  • 至少在GCC中,如果我们提供生成汇编代码的选项,编译器会通过创建一个包含汇编代码的文件来服从。但是,当我们简单地运行命令而没有任何选项时,它不会在内部生成汇编代码吗? 如果是,那么为什么它需要首先生成一个汇编代码,然后将其翻译成机器语言?

  • 我在第5行得到一个错误,上面说“未处理的异常IOException,InvalidFormatException”

  • 问题内容: 当Java编译器将原语自动包装到包装类时,它在幕后生成什么代码?我想象它调用: 包装器上的valueOf()方法 包装器的构造函数 还有其他魔术吗? 问题答案: 您可以使用该工具亲自查看。编译以下代码: 编译和反汇编: 输出为: 因此,如您所见,自动装箱将调用static方法,而自动拆箱将在给定对象上调用。没什么,真的- 只是语法糖。