我想知道如何在我的C源文件上使用GCC来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成什么。你可以用Java做到这一点,但我还没有找到一种方法与GCC。
我试图在汇编中重写一个C方法,看看GCC是如何做的,这将是一个很大的帮助。
我想知道如何在我的C源文件上使用GCC来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成什么。你可以用Java做到这一点,但我还没有找到一种方法与GCC。
我试图在汇编中重写一个C方法,看看GCC是如何做的,这将是一个很大的帮助。
当前回答
在基于x86的系统上使用-S开关到GCC,默认情况下会生成AT&T语法的转储,可以使用-masm=att开关指定,如下所示:
gcc -S -masm=att code.c
然而,如果你想用Intel语法生成一个转储,你可以使用-masm= Intel开关,如下所示:
gcc -S -masm=intel code.c
(两者都将code.c转储到各自的语法中,转储到文件代码中。分别)
为了用objdump产生类似的效果,你需要使用——disassemble -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
and
$ 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
其他回答
godbolt是一个非常有用的工具,他们的列表只有c++编译器,但你可以使用-x C标志,以便让它把代码视为C。它会为你的代码并排生成一个程序集列表,你可以使用Colourise选项生成彩色条,以直观地表明哪些源代码映射到生成的程序集。例如下面的代码:
#include <stdio.h>
void func()
{
printf( "hello world\n" ) ;
}
使用以下命令行:
-x c -std=c99 -O3
和Colourise将生成以下内容:
你可以像objdump一样使用gdb。
本文节选自http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64
下面是英特尔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.
在gcc或g++上使用-Wa,-adhln作为选项来生成到标准输出的清单输出。
佤邦,……是用于汇编程序部分的命令行选项(在C/++编译后在gcc/g++中执行)。它在内部调用(Windows中的as.exe)。 看到
>——帮助
作为命令行查看GCC内部汇编工具的更多帮助
如果您给GCC提供-fverbose-asm标志,它就会
在生成的程序集代码中添加额外的注释信息,使其更具可读性。 […新增的评论包括: 编译器版本和命令行选项的信息, 与汇编指令相关联的源代码行,格式为FILENAME:LINENUMBER:CONTENT OF LINE, 提示哪些高级表达式对应于各种汇编指令操作数。
使用-S(注意:大写S)切换到GCC,它将把程序集代码发送到扩展名为. S的文件中。例如,命令如下:
gcc -O2 -S -c foo.c