2013-10-06 81 views
0

我仍然在學習彙編語言和C語言,但現在我正試圖理解編譯器是如何工作的。我這裏有一個簡單的代碼:調試C程序(int聲明)

int sub() 
{ 
    return 0xBEEF; 
} 
main() 
{ 
    int a=10; 
    sub(); 
} 

現在我知道CPU已經是如何工作的,跳進框架和子程序等 什麼,我不明白是程序「商店」的局部變量。在這種情況下,在主框架?

這裏是調試器主框架:在

0x080483f6 <+0>:  push %ebp 
    0x080483f7 <+1>:  mov %esp,%ebp 
    0x080483f9 <+3>:  sub $0x10,%esp 
=> 0x080483fc <+6>:  movl $0xa,-0x4(%ebp) 
    0x08048403 <+13>: call 0x80483ec <sub> 
    0x08048408 <+18>: leave 
    0x08048409 <+19>: ret 

我有 「INT A = 10;」這就是爲什麼偏移量6有箭頭的原因。 因此,主要的功能開始別人推EBP唧唧歪歪等,然後我不明白這一點:

0x080483f9 <+3>:  sub $0x10,%esp 
=> 0x080483fc <+6>:  movl $0xa,-0x4(%ebp) 

爲什麼在ESP做子?是棧上的變量'a',堆棧指針的偏移量爲-0x4?

只是爲了清除這裏的想法:D

在此先感謝!

+0

出於好奇,你使用gcc嗎?如果是,哪個版本? – BlackBear

+0

gcc版本4.7.3(Ubuntu/Linaro 4.7.3-1ubuntu1) – int3

回答

2
0x080483f9 <+3>:  sub $0x10,%esp 

你會在每個函數中找到這樣的指令。它的目的是創建一個合適大小的堆棧框架,以便該函數可以存儲它的本地數據(請記住堆棧向後生長!)。
在這種情況下,堆棧幀有點太大。這是因爲默認情況下,gcc(從2.96開始)將堆棧幀填充到16個字節的邊界,以說明需要打包的128位向量對齊到16個字節的SSEx指令。 (參考文獻here)。

=> 0x080483fc <+6>:  movl $0xa,-0x4(%ebp) 

此行正在將a初始化爲正確的值(0xa = 10d)。本地總是被引用一個相對於ebp的偏移量,這標記了堆棧幀的開始(因此包含在ebp和esp之間)。

+0

'0x10'是十進制的'16'。那麼爲什麼'sub'指令意味着堆棧幀的大小爲4個字節? – us2012

+0

@ us2012:你完全正確,我忽略了這一點......而我只是休息一下;) – BlackBear

+0

好得多,+1 :)如果你對*爲什麼有一個解釋*爲什麼堆棧框架似乎比要求的大,會很棒。 – us2012