【发布时间】:2019-07-20 15:07:17
【问题描述】:
我试图理解一段反汇编代码中的行,如下所示。我想知道以下内容:
-
sub $0x10,%esp:为什么我们要在栈顶分配 16 个字节?我期望指针变量只有 4 个字节。 -
movl $0x0,-0x8(%ebp):为什么我们要将值 0x0 移到堆栈上?这是二进制文件的起始地址吗? -
nop:这段代码中 nop 指令的目的是什么?
这是反汇编的二进制文件:
Contents of section .text:
0000 5589e583 ec10c745 fc000000 0090c9c3 U......E........
Contents of section .rodata:
0000 48656c6c 6f00 Hello.
Contents of section .comment:
0000 00474343 3a202855 62756e74 7520352e .GCC: (Ubuntu 5.
0010 342e302d 36756275 6e747531 7e31362e 4.0-6ubuntu1~16.
0020 30342e31 30292035 2e342e30 20323031 04.10) 5.4.0 201
0030 36303630 3900 60609.
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 017c0801 .........zR..|..
0010 1b0c0404 88010000 1c000000 1c000000 ................
0020 00000000 10000000 00410e08 8502420d .........A....B.
0030 054cc50c 04040000 .L......
Disassembly of section .text:
00000000 <my_function>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
d: 90 nop
e: c9 leave
f: c3 ret
这是 C 代码:
void my_function () {
char* my_string = "Hello";
}
【问题讨论】:
-
此代码是否来自未经优化编译的目标文件 (
.o)? -
代码是在没有优化的情况下构建的。减 16 的使用可能与 64 位 System V ABI 有关,该 ABI 在函数调用中要求 16 字节对齐。您似乎正在转储目标文件。
c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)的值为 0 被移动,因为它是一个将被重新定位的占位符。使用-r选项和objdump让它转储重定位条目。如果您要转储可执行文件,则应修复重定位。 -
在这种情况下,
nop是某些版本的 GCC 在没有优化的情况下编译时生成的某种工件。打开优化,它应该与功能的其余部分一起消失;-) -
godbolt.org/z/0OP6s4 - ayyy
-
@melpomene :我在评论中建议优化可能会消除函数的主体,因为您对字符串不做任何事情。尝试将
my_string设为volatile指针以强制它为该字符串变量生成代码。例如:godbolt.org/z/JCFEsl