測試是在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可移植性庫或許多等價的函數)知道這些函數是如何定義的,可以讓我們準確地知道它在做什麼 –