使用 GCC 生成可读的程序集? [英] Using GCC to produce readable assembly?
问题描述
我想知道如何在我的 C 源文件上使用 GCC 来转储机器码,所以我可以看到我的代码被编译成什么.你可以用 Java 做到这一点,但我一直没能找到用 GCC 的方法.
I was wondering how to use GCC on my C source file to dump a mnemonic version of the machine code so I could see what my code was being compiled into. You can do this with Java but I haven't been able to find a way with GCC.
我正在尝试用汇编重写一个 C 方法,看看 GCC 是如何做到的,这将是一个很大的帮助.
I am trying to re-write a C method in assembly and seeing how GCC does it would be a big help.
推荐答案
如果您使用调试符号进行编译(将 -g
添加到您的 GCC 命令行,即使您还使用了 -O3
1),您可以使用 objdump -S
来生成与 C 源代码交错的更具可读性的反汇编.
If you compile with debug symbols (add -g
to your GCC command line, even if you're also using -O3
1),
you can use objdump -S
to produce a more readable disassembly interleaved with C source.
>objdump --help
[...]
-S, --source Intermix source code with disassembly
-l, --line-numbers Include line numbers and filenames in output
objdump -drwC -Mintel
不错:
-r
在重定位时显示符号名称(因此您会在下面的call
指令中看到puts
)-R
显示动态链接重定位/符号名称(对共享库有用)-C
破坏 C++ 符号名称-w
是宽";模式:它不换行机器码字节-Mintel
:使用类似 GAS/binutils MASM 的.intel_syntax noprefix
语法代替 AT&T-S
:将源代码行与反汇编交错.
-r
shows symbol names on relocations (so you'd seeputs
in thecall
instruction below)-R
shows dynamic-linking relocations / symbol names (useful on shared libraries)-C
demangles C++ symbol names-w
is "wide" mode: it doesn't line-wrap the machine-code bytes-Mintel
: use GAS/binutils MASM-like.intel_syntax noprefix
syntax instead of AT&T-S
: interleave source lines with disassembly.
您可以在 ~/.bashrc
中添加类似 alias disas=objdump -drwCS -Mintel"
的内容.如果不在 x86 上,或者如果您喜欢 AT&T 语法,请省略 -Mintel
.
You could put something like alias disas="objdump -drwCS -Mintel"
in your ~/.bashrc
. If not on x86, or if you like AT&T syntax, omit -Mintel
.
示例:
> 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
注意这个不是使用-r
所以call rel32=-4
没有用puts注释
符号名称.并且看起来像一个坏掉的call
,它跳到了main 中调用指令的中间.请记住,调用编码中的 rel32
位移只是一个占位符,直到链接器填充实际偏移量(在这种情况下为 PLT 存根,除非您静态链接 libc).
Note that this isn't using -r
so the call rel32=-4
isn't annotated with the puts
symbol name. And looks like a broken call
that jumps into the middle of the call instruction in main. Remember that the rel32
displacement in the call encoding is just a placeholder until the linker fills in a real offset (to a PLT stub in this case, unless you statically link libc).
脚注 1:交错源代码可能很混乱,而且对优化构建没有太大帮助;为此,请考虑 https://godbolt.org/ 或其他可视化哪些指令与哪些源代码行对应的方法.在优化的代码中有 并不总是说明指令的单个源代码行,但调试信息将为每个 asm 指令选择一个源代码行.
Footnote 1: Interleaving source can be messy and not very helpful in optimized builds; for that, consider https://godbolt.org/ or other ways of visualizing which instructions go with which source lines. In optimized code there's not always a single source line that accounts for an instruction but the debug info will pick one source line for each asm instruction.
这篇关于使用 GCC 生成可读的程序集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!