You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C语言Hello World目标文件反汇编后无printf与字符串?

问题:反汇编Hello World目标文件找不到"Hello, World!"字符串及printf相关内容

我用gcc Hello.c -c Hello.o将C源码编译为目标文件,再通过objdump -D -Mamd64 ./Hello.o >> a.s反汇编生成a.s文件,但在结果里看不到"Hello, World!"字符串,也找不到printf相关的汇编代码。

C源码

#include <stdio.h>
int main(void)
{
    printf("Hello, World!");
    return 0;
}

反汇编文件内容

./Hello.o:     file format pe-i386


Disassembly of section .text:

00000000 <_main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 10                sub    $0x10,%esp
   9:   e8 00 00 00 00          call   e <_main+0xe>
   e:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
  15:   e8 00 00 00 00          call   1a <_main+0x1a>
  1a:   b8 00 00 00 00          mov    $0x0,%eax
  1f:   c9                      leave  
  20:   c3                      ret    
  21:   90                      nop
  22:   90                      nop
  23:   90                      nop

Disassembly of section .rdata:

00000000 <.rdata>:
   0:   48                      dec    %eax
   1:   65 6c                   gs insb (%dx),%es:(%edi)
   3:   6c                      insb   (%dx),%es:(%edi)
   4:   6f                      outsl  %ds:(%esi),(%dx)
   5:   2c 20                   sub    $0x20,%al
   7:   57                      push   %edi
   8:   6f                      outsl  %ds:(%esi),(%dx)
   9:   72 6c                   jb     77 <.rdata+0x77>
   b:   64 21 00                and    %eax,%fs:(%eax)
    ...

Disassembly of section .rdata$zzz:

00000000 <.rdata$zzz>:
   0:   47                      inc    %edi
   1:   43                      inc    %ebx
   2:   43                      inc    %ebx
   3:   3a 20                   cmp    (%eax),%ah
   5:   28 4d 69                sub    %cl,0x69(%ebp)
   8:   6e                      outsb  %ds:(%esi),(%dx)
   9:   47                      inc    %edi
   a:   57                      push   %edi
   b:   2e 6f                   outsl  %cs:(%esi),(%dx)
   d:   72 67                   jb     76 <.rdata$zzz+0x76>
   f:   20 47 43                and    %al,0x43(%edi)
  12:   43                      inc    %ebx
  13:   2d 36 2e 33 2e          sub    $0x2e332e36,%eax
  18:   30 2d 31 29 20 36       xor    %ch,0x36202931
  1e:   2e 33 2e                xor    %cs:(%esi),%ebp
  21:   30 00                   xor    %al,(%eax)
    ...

Disassembly of section .eh_frame:

00000000 <.eh_frame>:
   0:   14 00                   adc    $0x0,%al
   2:   00 00                   add    %al,(%eax)
   4:   00 00                   add    %al,(%eax)
   6:   00 00                   add    %al,(%eax)
   8:   01 7a 52                add    %edi,0x52(%edx)
   b:   00 01                   add    %al,(%ecx)
   d:   7c 08                   jl     17 <.eh_frame+0x17>
   f:   01 1b                   add    %ebx,(%ebx)
  11:   0c 04                   or     $0x4,%al
  13:   04 88                   add    $0x88,%al
  15:   01 00                   add    %eax,(%eax)
  17:   00 1c 00                add    %bl,(%eax,%eax,1)
  1a:   00 00                   add    %al,(%eax)
  1c:   1c 00                   sbb    $0x0,%al
  1e:   00 00                   add    %al,(%eax)
  20:   04 00                   add    $0x0,%al
  22:   00 00                   add    %al,(%eax)
  24:   21 00                   and    %eax,(%eax)
  26:   00 00                   add    %al,(%eax)
  28:   00 41 0e                add    %al,0xe(%ecx)
  2b:   08 85 02 42 0d 05       or     %al,0x50d4202(%ebp)
  31:   5d                      pop    %ebp
  32:   c5 0c 04                lds    (%esp,%eax,1),%ecx
  35:   04 00                   add    $0x0,%al
    ...

原因及解决办法

1. 目标文件未完成链接,printf是外部引用

-c参数只做编译不链接,生成的目标文件里只会保留对printf的调用占位,不会包含printf的实现代码。你看到的call 00000000是链接前的占位地址,链接阶段才会替换成printf的真实地址。

2. 字符串存在但被当成指令解析

"Hello, World!"的ASCII码是48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21,对应你反汇编结果里.rdata节的前13个字节。但objdump -D会把所有节都当成代码段解析,所以把字符串字节翻译成了dec、insb这些无关指令。要查看原始字符串,用objdump -s Hello.o,它会以字节和ASCII形式显示各节内容。

3. 指令集参数不匹配

你的目标文件是32位PE格式(pe-i386),但反汇编时用了-Mamd64(64位x86语法),导致指令显示异常。应该用32位语法参数,比如-Mi386或-Mintel。


正确操作步骤

  • 生成可执行文件(包含链接):

    gcc Hello.c -o Hello.exe
    
  • 反汇编可执行文件:

    objdump -D -Mi386 Hello.exe >> a.s
    

    这样就能看到printf的调用逻辑(如果是动态链接会显示PLT stub,静态链接则会包含完整的printf实现),同时字符串也会在对应数据节中正确显示。

  • 查看目标文件的字符串和符号:
    若只想看目标文件里的字符串和符号引用,不用反汇编代码:

    objdump -s -t Hello.o
    

    -s显示各节的字节和ASCII内容,-t显示符号表,能看到printf是未定义的外部符号。

内容的提问来源于stack exchange,提问作者rahulc0dy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 23:12:33