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

在32位编译反汇编结果中定位"Hello"字符串及指令疑问

OS-dev代码反汇编疑问解答

问题背景

正在学习Nick Blundell所著《OS-dev》书籍的5.1.4节,对一段C代码的反汇编结果存在两个疑问:

编写的C代码(string.c)

void my_function()
{
    char* str = "Hello";
}

编译、链接、反汇编命令

在64位Linux环境下以32位模式操作:

  • 编译:
gcc -ffreestanding -fno-pie -m32 -c string.c -o string.o
  • 链接:
ld -m elf_i386 -o string.bin -Ttext 0x0 --oformat binary string.o
  • 反汇编:
ndisasm -b 32 string.bin > string.dis

得到的反汇编结果

00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  83EC10            sub esp,byte +0x10
00000006  C745FC00100000    mov dword [ebp-0x4],0x1000
0000000D  90                nop
0000000E  C9                leave
0000000F  C3                ret

疑问:

  • 编译器分配了16字节栈空间,但反汇编结果里找不到"Hello"字符串的位置
  • 不理解第4行mov dword [ebp-0x4],0x1000指令的作用

解答

1. 找不到"Hello"字符串的原因

你使用ld链接时指定了--oformat binary,这个参数会让链接器只输出可执行的.text段内容。而C语言中的字符串常量"Hello"默认被编译器放在.rodata(只读数据段)中,不属于.text段。二进制输出模式下,非.text段的内容不会被打包到string.bin里,所以反汇编结果里自然看不到它。

要验证这一点,可以直接反汇编目标文件查看所有段:

objdump -d -M intel -m i386 string.o

或者用readelf -S string.o查看目标文件的段信息,就能在.rodata段里找到"Hello\0"的内容。

2. 第4行指令的作用

这条指令是给栈上的str变量赋值:ebp-0x4是str在栈帧中的位置,0x1000是"Hello"字符串在最终程序中的内存地址。

因为你链接时用了-Ttext 0x0,指定.text段从0x0地址开始,而.rodata段默认会被链接器放在.text段之后,所以字符串的起始地址被分配到了0x1000(这个地址可能因编译器/链接器版本略有不同)。

另外,栈上分配16字节(sub esp,0x10)是因为gcc的16字节栈对齐规则——32位模式下,编译器会强制栈帧对齐到16字节边界,即使只需要4字节存放指针,也会额外分配空间满足对齐要求。末尾的nop指令也是为了让函数指令序列符合对齐规范。


内容的提问来源于stack exchange,提问作者Alexander the Great

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:49:56