测试是在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
,我是对的吗?)根据我的观察,第一个函数使用的模式很少见,约为5%的gcc
用O2
编译中等大小的C程序。
因此,这里是我的问题:
为什么编译器生成类似quoterag_n
方式函数序言说明?前三条指令的确切含义是从地址0x804a6f0
开始的?
为什么编译器总是在sub
然后access
模式之后生成函数序言指令? (如quoterag
)
我清楚吗?非常感谢
显示生成此代码或引用“quotearg_n_options”代码可能很有用(可能是GNUlib可移植性库或许多等价的函数)知道这些函数是如何定义的,可以让我们准确地知道它在做什么 –