使用 GCC 生成可读的程序集? [英] Using GCC to produce readable assembly?

查看:21
本文介绍了使用 GCC 生成可读的程序集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何在我的 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 命令行,即使您还使用了 -O31),您可以使用 objdump -S 来生成与 C 源代码交错的更具可读性的反汇编.

If you compile with debug symbols (add -g to your GCC command line, even if you're also using -O31), 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 see puts in the call 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆