c - gcc objdump 程序集调试

标签 c gcc assembly gdb disassembly

我正在尝试将 C 代码更改为汇编代码。

起初,我使用 gcc 和 objdump 函数从 c 代码中提取汇编代码。

C 代码只是简单的 printf 代码。

#include <stdio.h>

int main(){
    printf("this\n");
    return 0;
}


gcc -c -S -O0 test.c
objdump -dS test.o > test.txt

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   bf 00 00 00 00          mov    $0x0,%edi
   9:   e8 00 00 00 00          callq  e <main+0xe>
   e:   b8 00 00 00 00          mov    $0x0,%eax
  13:   5d                      pop    %rbp 
  14:   c3                      retq 

在这个汇编代码中,
我很好奇为什么 callq 指令目的地是 e

所以我在 gdb 中运行这段代码使用

主要问题
    (gdb) disas main
Dump of assembler code for function main:
   0x0000000000400526 <+0>: push   %rbp
   0x0000000000400527 <+1>: mov    %rsp,%rbp
   0x000000000040052a <+4>: mov    $0x4005c4,%edi
   0x000000000040052f <+9>: callq  0x400400 <puts@plt>
   0x0000000000400534 <+14>: mov    $0x0,%eax
   0x0000000000400539 <+19>: pop    %rbp
   0x000000000040053a <+20>: retq 

在这段代码中,我假设 0x400400 是 printf 函数的地址。

为什么 objdump 和 gdb 的汇编代码显示不同的结果?

如何让 objdump 结果显示正确的 callq 目的地?

最佳答案

当您运行 objdump 时命令不是反汇编最终的可执行文件,而是反汇编编译器生成的目标文件( test.o )。我对您执行了类似的步骤(使用您的代码)(在 GDB 中编译和运行 objdumpdissas),除了我执行了 objdump在链接的可执行文件上而不是在目标文件上(这意味着我没有使用 -c 标志进行编译)。输出如下:

objdump -dS a.out:
1140:       55                      push   %rbp
1141:       48 89 e5                mov    %rsp,%rbp
1144:       48 83 ec 10             sub    $0x10,%rsp
1148:       48 8d 3d b5 0e 00 00    lea    0xeb5(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
114f:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
1156:       b0 00                   mov    $0x0,%al
1158:       e8 d3 fe ff ff          callq  1030 <printf@plt>
115d:       31 c9                   xor    %ecx,%ecx
115f:       89 45 f8                mov    %eax,-0x8(%rbp)
1162:       89 c8                   mov    %ecx,%eax
1164:       48 83 c4 10             add    $0x10,%rsp
1168:       5d                      pop    %rbp
1169:       c3                      retq   
116a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

GDB:
(gdb) disas main
Dump of assembler code for function main:
   0x0000000000001140 <+0>:     push   %rbp
   0x0000000000001141 <+1>:     mov    %rsp,%rbp
   0x0000000000001144 <+4>:     sub    $0x10,%rsp
   0x0000000000001148 <+8>:     lea    0xeb5(%rip),%rdi        # 0x2004
   0x000000000000114f <+15>:    movl   $0x0,-0x4(%rbp)
   0x0000000000001156 <+22>:    mov    $0x0,%al
   0x0000000000001158 <+24>:    callq  0x1030 <printf@plt>
   0x000000000000115d <+29>:    xor    %ecx,%ecx
   0x000000000000115f <+31>:    mov    %eax,-0x8(%rbp)
   0x0000000000001162 <+34>:    mov    %ecx,%eax
   0x0000000000001164 <+36>:    add    $0x10,%rsp
   0x0000000000001168 <+40>:    pop    %rbp
   0x0000000000001169 <+41>:    retq   
End of assembler dump.

如您所见,两个反汇编是相同的,除了一些细微的语法差异(例如,GDB 前缀是 0x 的地址)。

关于c - gcc objdump 程序集调试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52072013/

相关文章:

c++ - 难以理解 free() 的行为

c - 不兼容指针赋值的技术合法性

c - 为什么 ret 会随着优化而消失?

c++ - 为什么这个程序的输出在 C 和 C++ 之间不同?

ubuntu - 汇编通过堆栈传递变量

c - 不同版本操作系统的 OpenMP 性能差异

关于 C 中 fwrite() 和 fread() 参数的混淆

linux - 如何调试需要用户输入的 NASM 汇编程序?

c - 删除C中字符串的前导空格并复制到dest数组

assembly - 在汇编 x86 中交换位(或只是访问它们)