使用GCC生成可读组件?

时间:2009-08-17 19:22:17

标签: c gcc assembly

我想知道如何在我的C源文件中使用GCC来转储机器代码的助记符版本,以便我可以看到我的代码被编译成什么。您可以使用Java执行此操作,但我无法找到GCC的方法。

我正在尝试在汇编中重新编写一个C方法,看看GCC是如何做的,这将是一个很大的帮助。

10 个答案:

答案 0 :(得分:309)

如果使用调试符号进行编译,则可以使用objdump生成更易读的反汇编。

>objdump --help
[...]
-S, --source             Intermix source code with disassembly
-l, --line-numbers       Include line numbers and filenames in output

objdump -drwC -Mintel很不错:

  • -r在重定位时显示符号名称(因此,您可以在下面的puts说明中看到call
  • -R显示动态链接重定位/符号名称(对共享库有用)
  • -C demangles C ++符号名称
  • -w是“宽”模式:它不包装机器码字节
  • -Mintel:使用GAS / binutils MASM类.intel_syntax noprefix语法代替AT& T
  • -S:使用反汇编交错源代码行。

您可以在alias disas="objdump -drwCS -Mintel"

中添加~/.bashrc之类的内容

示例:

> gcc -g -c test.c
> objdump -d -M intel -S test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main(void)
{
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   83 e4 f0                and    esp,0xfffffff0
   6:   83 ec 10                sub    esp,0x10
    puts("test");
   9:   c7 04 24 00 00 00 00    mov    DWORD PTR [esp],0x0
  10:   e8 fc ff ff ff          call   11 <main+0x11>

    return 0;
  15:   b8 00 00 00 00          mov    eax,0x0
}
  1a:   c9                      leave  
  1b:   c3                      ret

答案 1 :(得分:93)

我想补充一下这些答案,如果你给gcc标志-fverbose-asm,它发出的汇编程序将会更加清晰。

答案 2 :(得分:72)

  

使用-S(注意:大写S)切换到GCC,它会将汇编代码发送到扩展名为.s的文件。例如,以下命令:

     

gcc -O2 -S foo.c

     

将生成的汇编代码保留在文件foo.s。

直接从http://www.delorie.com/djgpp/v2faq/faq8_20.html翻录(但删除了错误的-c

答案 3 :(得分:48)

在基于x86的系统上使用-S切换到GCC会产生AT&amp; T语法转储,默认情况下可以使用-masm=att开关指定,如下所示:

gcc -S -masm=att code.c

如果您想以英特尔语法生成转储,则可以使用-masm=intel开关,如下所示:

gcc -S -masm=intel code.c

(两者都将code.c转储为各种语法,分别生成文件code.s

为了使用objdump产生类似的效果,您需要使用--disassembler-options= intel / att开关,一个示例(使用代码转储来说明语法上的差异) :

 $ objdump -d --disassembler-options=att code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    0x4(%esp),%ecx
 80483c8:   83 e4 f0                and    $0xfffffff0,%esp
 80483cb:   ff 71 fc                pushl  -0x4(%ecx)
 80483ce:   55                      push   %ebp
 80483cf:   89 e5                   mov    %esp,%ebp
 80483d1:   51                      push   %ecx
 80483d2:   83 ec 04                sub    $0x4,%esp
 80483d5:   c7 04 24 b0 84 04 08    movl   $0x80484b0,(%esp)
 80483dc:   e8 13 ff ff ff          call   80482f4 <puts@plt>
 80483e1:   b8 00 00 00 00          mov    $0x0,%eax
 80483e6:   83 c4 04                add    $0x4,%esp 
 80483e9:   59                      pop    %ecx
 80483ea:   5d                      pop    %ebp
 80483eb:   8d 61 fc                lea    -0x4(%ecx),%esp
 80483ee:   c3                      ret
 80483ef:   90                      nop

$ objdump -d --disassembler-options=intel code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    ecx,[esp+0x4]
 80483c8:   83 e4 f0                and    esp,0xfffffff0
 80483cb:   ff 71 fc                push   DWORD PTR [ecx-0x4]
 80483ce:   55                      push   ebp
 80483cf:   89 e5                   mov    ebp,esp
 80483d1:   51                      push   ecx
 80483d2:   83 ec 04                sub    esp,0x4
 80483d5:   c7 04 24 b0 84 04 08    mov    DWORD PTR [esp],0x80484b0
 80483dc:   e8 13 ff ff ff          call   80482f4 <puts@plt>
 80483e1:   b8 00 00 00 00          mov    eax,0x0
 80483e6:   83 c4 04                add    esp,0x4
 80483e9:   59                      pop    ecx
 80483ea:   5d                      pop    ebp
 80483eb:   8d 61 fc                lea    esp,[ecx-0x4]
 80483ee:   c3                      ret    
 80483ef:   90                      nop

答案 4 :(得分:34)

godbolt是一个非常有用的工具,他们列出的只有C ++编译器,但你可以使用-x c标志,以便将代码视为C.然后它会为你生成一个汇编列表代码并排,您可以使用Colourise选项生成彩色条,以直观地指示哪个源代码映射到生成的程序集。例如,以下代码:

#include <stdio.h>

void func()
{
  printf( "hello world\n" ) ;
}

使用以下命令行:

-x c -std=c99 -O3

Colourise将生成以下内容:

enter image description here

答案 5 :(得分:21)

您是否尝试gcc -S -fverbose-asm -O source.c然后查看生成的source.s汇编程序文件?

生成的汇编程序代码进入source.s(您可以使用-o 汇编程序文件名来覆盖它; -fverbose-asm选项要求编译器发出一些汇编语句“解释”生成的汇编代码。 -O选项要求编译器优化一点(可以使用-O2-O3优化更多。)

如果您想了解gcc正在做什么,请尝试传递-fdump-tree-all但要小心:您将获得数百个转储文件。

顺便说一下,GCC可以通过pluginsMELT扩展(扩展GCC的高级域名特定语言;我在2017年放弃了)

答案 6 :(得分:19)

您可以像使用objdump一样使用gdb。

摘录摘自http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


以下是显示Intel x86的混合源+程序集的示例:

  (gdb) disas /m main
Dump of assembler code for function main:
5       {
0x08048330 :    push   %ebp
0x08048331 :    mov    %esp,%ebp
0x08048333 :    sub    $0x8,%esp
0x08048336 :    and    $0xfffffff0,%esp
0x08048339 :    sub    $0x10,%esp

6         printf ("Hello.\n");
0x0804833c :   movl   $0x8048440,(%esp)
0x08048343 :   call   0x8048284 

7         return 0;
8       }
0x08048348 :   mov    $0x0,%eax
0x0804834d :   leave
0x0804834e :   ret

End of assembler dump.

答案 7 :(得分:13)

使用-S(注意:大写S)切换到GCC,它会将汇编代码发送到扩展名为.s的文件。例如,以下命令:

gcc -O2 -S -c foo.c

答案 8 :(得分:4)

我没有给gcc一个镜头,但是在g ++的情况下。以下命令对我有用。 -g用于调试构建和-Wa,-adhln传递给汇编程序以列出源代码

g ++ -g -Wa,-adhln src.cpp

答案 9 :(得分:0)

在gcc或g ++上使用 -Wa,-adhln 作为选项,以生成标准输出的列表输出。

-Wa,...用于汇编器部分的命令行选项(在C / ++编译后在gcc / g ++中执行)。它在内部(在Windows中为as.exe)调用 as 。 参见

>为--help

作为命令行以查看gcc内的汇编器工具的更多帮助