【发布时间】:2015-09-25 10:45:32
【问题描述】:
测试在32-bit x86。我用gcc 4.2编译了代码,优化级别o2。我把C代码编译成二进制,然后用objdump反汇编。
这里有两个用于函数序言的指令序列:
0804a6f0 <quotearg_n>:
804a6f0: 8b 44 24 04 mov 0x4(%esp),%eax
804a6f4: b9 ff ff ff ff mov $0xffffffff,%ecx
804a6f9: 8b 54 24 08 mov 0x8(%esp),%edx
804a6fd: c7 44 24 04 40 e1 04 movl $0x804e140,0x4(%esp)
804a704: 08
804a705: e9 c6 fa ff ff jmp 804a1d0 <quotearg_n_options>
804a70a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
0804a730 <quotearg>:
804a730: 83 ec 1c sub $0x1c,%esp
804a733: 8b 44 24 20 mov 0x20(%esp),%eax
804a737: c7 04 24 00 00 00 00 movl $0x0,(%esp)
804a73e: 89 44 24 04 mov %eax,0x4(%esp)
804a742: e8 a9 ff ff ff call 804a6f0 <quotearg_n>
804a747: 83 c4 1c add $0x1c,%esp
804a74a: c3 ret
804a74b: 90 nop
804a74c: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
请注意,在函数quotearg 中,寄存器esp 在用于访问堆栈并获取一些参数之前会减少0x1c。准确地说,根据我的经验,我认为sub 然后access 模式对于使用O2 编译的指令是很常见的。
但是,注意在函数quotearg_n中,寄存器esp直接加上0x4来访问堆栈。 (我认为地址0x804a6f0的指令的意思是将调用站点的返回地址注册eax,对吗..?)根据我的观察,第一个函数使用的模式很少见,大约gcc 使用 O2 编译的中等大小 C 程序的 5%。
所以这是我的问题:
为什么编译器生成函数序言指令的方式类似于quoterag_n?前三个指令从地址0x804a6f0 开始的确切含义是什么?
为什么编译器不总是按照sub 然后access 模式生成函数序言指令? (如quoterag)
我说清楚了吗?非常感谢
【问题讨论】:
-
可能有助于显示生成此代码的代码或对
quotearg_n_options代码的引用(可能是 GNUlib 可移植库或许多等效库)。知道这些函数是如何定义的,我们就可以准确地知道它在做什么。