2014-10-05 104 views
-1

我真的不明白爲什麼gcc在調用函數之前已經減去12來esp。彙編堆棧管理通過%esp

pushl %ebp 
    movl %esp,%ebp 
    sub $12,%esp 

    socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    movl $AF_INET,(%esp) 
+0

'sub'是減法不加法;)它是分配局部變量,與套接字調用沒有任何關係。 – Jester 2014-10-05 17:19:00

+0

呵呵:-)編輯。我試圖讓this.esp指向棧,從它減去一些值使它指向一個較低的地址,然後它之間的內存用於變量?我是否有意義? – asla 2014-10-05 17:24:36

+0

是的,就是這樣。 – Jester 2014-10-05 17:26:46

回答

1

目前* 86 ABI要求堆棧指針對齊在函數調用時模16。這是堆棧指針無法解釋的調整的典型原因。

*我說目前,因爲GCC實際上單方面改變了ABI,並在3.x系列的某個地方引入了這個要求。我沒有方便的參考,但也許有人可以提供它們。此更改旨在優化SIMD指令的使用,但實際上並非實現此目的所必需的,並且在舊代碼回調到假定對齊的新代碼時,最終會破壞與舊代碼的ABI兼容性。整個故事是一個大混亂。

+0

如果在調用時堆棧在16字節邊界上對齊,則在32位X86上,該調用將4字節返回地址壓入堆棧,堆棧不再位於16字節的邊界上。也只有被調用函數的第一個參數將在16字節的邊界上,其餘的將取決於第一個參數的大小以及其餘參數的對齊規則。我不確定這是什麼意思。 – rcgldr 2014-10-06 00:49:43

+0

@rcgldr:關鍵是被調用者在進入時可以知道堆棧指針16的對齊方式,從而可以創建與16字節邊界對齊的自動存儲對象,而不必對齊堆棧指針本身。當然,對齊堆棧指針本身並不重要,只會將需要對象對齊到16個字節的函數花費在成本上,並且避免了破壞與舊ABI的兼容性,這就是爲什麼整個約定完全愚蠢的原因。但是,這是歷史...... – 2014-10-06 02:03:59

+0

或者被調用者可以只添加一條指令到典型的輸入序列:推ebp | mov ebp,esp |和esp,0fffffff0h | 。 – rcgldr 2014-10-06 03:18:09

0

首先,您正在推動減少堆棧指針值的基址指針的值。由於推送操作實際上會導致地址斷開。然後,c程序的堆棧框架由代碼段組成,在代碼段上面有函數的參數,上面的函數位於sp上。現在,當你想訪問傳遞給函數的第一個參數時,你需要添加12個字節,因爲最後需要彈出3個單詞來獲取該參數。

http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/stack.html

,我發現這個資源非常有用