我知道我可以使用以下命令获取编译器生成的汇编程序 source 代码:
gcc -S ...
即使这令人讨厌,也没有给我一个目标文件作为整个过程的一部分。
但是如何获得编译代码的所有内容?我指的是地址,生成的字节等等。
gcc -S
输出的指令不会告诉我有关指令长度或编码的任何信息,这就是我想要看到的内容。
答案 0 :(得分:10)
我喜欢objdump
,但最有用的选项并不明显 - 特别是如果你在包含重定位的目标文件上使用它,而不是最终的二进制文件。
objdump -d some_binary
做得很合理。
objdump -d some_object.o
不太有用,因为对外部函数的调用不会被有效地反汇编:
...
00000005 <foo>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 53 push %ebx
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
30: e8 fc ff ff ff call 31 <foo+0x2c>
35: 89 d8 mov %ebx,%eax
...
call
实际上是printf()
...添加-r
标志有助于此;它标志着重新安置。 objdump -dr some_object.o
给出:
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
30: e8 fc ff ff ff call 31 <foo+0x2c>
31: R_386_PC32 printf
...
然后,我发现将每行注释为<symbol+offset>
很有用。 objdump
有一个方便的选项,但它有关闭实际字节转储的烦人副作用 - objdump --prefix-addresses -dr some_object.o
给出:
...
00000005 <foo> push %ebp
00000006 <foo+0x1> mov %esp,%ebp
00000008 <foo+0x3> push %ebx
...
但事实证明你可以通过提供另一个模糊选项来撤消它,最后到达我最喜欢的objdump
咒语:
objdump --prefix-addresses --show-raw-insn -dr file.o
给出如下输出:
...
00000005 <foo> 55 push %ebp
00000006 <foo+0x1> 89 e5 mov %esp,%ebp
00000008 <foo+0x3> 53 push %ebx
...
00000029 <foo+0x24> c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
00000030 <foo+0x2b> e8 fc ff ff ff call 00000031 <foo+0x2c>
31: R_386_PC32 printf
00000035 <foo+0x30> 89 d8 mov %ebx,%eax
...
如果您使用调试符号构建(即使用-g
编译),并将-dr
替换为-Srl
,它将尝试使用相应的源注释输出线。
答案 1 :(得分:3)
获得快速列表的最简单方法是使用汇编程序的-a
选项,您可以通过将-Wa,-a
放在gcc
命令行上来执行此操作。您可以对选项使用各种修饰符来确切地影响出来的内容 - 请参阅as(1)手册页。
答案 2 :(得分:1)
gcc将生成汇编语言源文件。然后,您可以使用as -a yourfile.S
生成包含每条指令的偏移量和编码字节的列表。 -a
还有一些子选项来控制列表文件中显示的内容(as --help
会列出它们以及其他可用选项。)
答案 3 :(得分:0)
听起来像你想要一个反汇编程序。 objdump
几乎是标准版(Mac OS X上的otool
);与链接器为您提供的任何映射文件信息一致,对象文件的反汇编应该为您提供所需的一切。
答案 4 :(得分:0)
nasm -f elf xx.asm -l x.lst
gcc xx.c xx.o -o xx
生成一个'list'文件x.lst,仅适用于xx.asm
对于xx.c以及xx.asm你可以编译它们然后使用'gdb' - gnu debugger