小编典典

使用 GCC 生成可读的程序集?

all

我想知道如何在我的 C
源文件上使用GCC来转储机器代码的助记符版本,以便我可以看到我的代码被编译成什么。你可以用
Java 做到这一点,但我无法找到 GCC 的方法。

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


阅读 87

收藏
2022-04-24

共1个答案

小编典典

如果您使用调试符号进行编译(添加-g到您的 GCC 命令行,即使您也在使用-O31),您可以使用objdump -S生成与 C
源代码交错的更具可读性的反汇编。

>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对 C++ 符号名称进行解码
  • -w是“宽”模式:它不会换行机器代码字节
  • -Mintel: 使用 GAS/binutils 类似 MASM 的.intel_syntax noprefix语法而不是 AT&T
  • -S: 将源代码行与反汇编交错。

你可以alias disas="objdump -drwCS -Mintel"在你的~/.bashrc. 如果不在 x86 上,或者如果您喜欢
AT&T 语法,请省略-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)。


脚注 1
:交错源代码可能很混乱,对优化构建没有多大帮助;为此,请考虑https://godbolt.org/或其他可视化哪些指令与哪些源代码行相关的方法。

2022-04-24