2012-06-24 73 views
8

我正在玩gcc -S以瞭解內存和堆棧是如何工作的。在這些戲劇中,我發現了幾件事情不清楚。你能幫我理解一下原因嗎?爲什麼gcc在創建彙編代碼時這樣做?

  1. 當調用函數的參數設置爲一個名爲一個它使用movesp,而不是push。有什麼優勢不使用push

  2. 函數,它的棧位於參數指向ebp + (N + offset)(其中N是爲返回地址保留的大小)。我期望看到esp - offset這更容易理解。到處使用ebp作爲基本點的原因是什麼?我知道這些是平等的,但無論如何?

  3. main開頭的這個魔法是什麼?爲什麼esp只能以這種方式進行初始化?

    and esp,0xfffffff0 
    

感謝,

+3

這可能是3個單獨的問題。無論如何,第三點的答案是堆棧對齊。 – Mysticial

回答

7

我會假設你是因爲在64位環境參數在寄存器傳遞32位環境下工作。

問題1

也許你在這裏傳遞一個浮點參數。您不能直接推送這些數據,因爲在32位運行時,push指令一次推送4個字節,因此您必須分解數值。有時候從esp減去8會更容易,它們會將8字節的四字轉換爲[esp]

問題2

ebp被頻繁用於索引堆棧幀的參數,並在當地人的32位代碼。這允許幀內的偏移量即使在堆棧指針移動時也是固定的。例如,考慮

void f(int x) { 
    int a; 
    g(x, 5); 
} 

現在,如果你只esp訪問堆棧幀的內容,然後a[esp],返回地址將在[esp+4]x將在[esp+8]。現在讓我們生成代碼來調用g。我們必須先推5,然後按x。但推5後,x的偏移量從esp改變了!這就是使用ebp的原因。通常在進入功能時,我們將舊值ebp保存,然後將esp複製到ebp。現在ebp可用於訪問堆棧幀內容。當我們處於爭論的中間時,它不會移動。

問題3

and指令零出的esp的最後4位,它對準到一個16字節邊界。由於堆棧向下增長,這是很好的和安全的。

+1

問題3:它過去4位是零 – hirschhornsalz

+0

哦,我的,謝謝@drhirsch。沒有思考就打字。可怕。非常感謝!編輯。 –

相關問題