2014-09-05 38 views
4

所以我想寫一些x86來爲結構分配內存。我的C代碼看起來像這樣...在x86程序集中的結構分配

struc *uno = malloc(sizeof(struc)); 
    uno->first = 0; 
    uno->second = 0; 
    uno->third = 0; 

    //And the struct 
    struct struc { 
     int first; 
     int second; 
     int *third; 
    } 

而且拆機的模樣......

pushl %ebp 
    movl %esp, %ebp 
    subl $40, %esp 
    movl $12, (%esp) 
    call malloc 
    movl %eax, -12(%ebp) 
    movl -12(%ebp), %eax 
    movl $0, (%eax) 
    movl -12(%ebp), %eax 
    movl $0, 4(%eax) 
    movl -12(%ebp), %eax 
    movl $0, 8(%eax) 
    movl $0, %eax 

所以,我有幾個問題...

1)的大小結構是16,但爲什麼組件只顯示它分配12?

2)什麼是對於

movl %eax, -12(%ebp) 
    movl -12(%ebp), %eax 

的意義不只是把EAX的內容到EBP的地址 - 12。然後第二個語句是多餘的?

3)爲什麼當沒有其他本地變量或參數要推入堆棧時,esp會減少40?我會認爲它只需要減少16。

任何幫助表示讚賞,以及任何我可能錯過了,你認爲有關。我很新裝配。謝謝。

+2

是什麼讓你覺得尺寸是16?你背後的理由是什麼? – 2014-09-05 20:05:09

回答

9

結構體的大小爲12.這兩個整數和指針在x86上都是4個字節,所以沒有填充並且結構體大小爲12.如果您不確定是否可以使用sizeof來詢問編譯器一個類型的大小。


你正在編譯沒有優化,所以代碼看起來有點低效。

​​3210

這就需要malloc,然後將保存在%eax局部變量uno的價值迴歸,儲存在-12(%ebp)。因此,這三條指令組成了對malloc的調用:準備堆棧,調用函數,保存返回值。

我們繼續下一行。

uno->first = 0; 

因爲沒有優化,編譯器不知道,%eax已經包含uno的價值,所以它再次加載它,然後寫入零到第一部件

movl -12(%ebp), %eax 
movl $0, (%eax) 

下一頁最多是

uno->second = 0; 

我們再一次的uno值加載到%eax,譜寫零,此時進入第二部件在偏移4

movl -12(%ebp), %eax 
movl $0, 4(%eax) 

你的想法,我敢肯定,我不需要解釋的最終分配。

嘗試使用優化進行編譯,輸出看起來非常不同。編譯器應該能夠將uno優化爲%eax,而不是放在堆棧上。爲什麼你認爲堆棧儲備應該是16個字節

movl $12, (%esp) 
call malloc 
movl $0, (%eax) 
movl $0, 4(%eax) 
movl $0, 8(%eax) 

我真的不知道:它可以產生這種代碼。我只看到需要4個字節,參數在上面的優化變體中傳遞給malloc。沒有優化,我會猜測8,參數4,局部變量4。但我不知道爲什麼函數爲堆棧保留了40個字節。也許答案可以在這些問題一個發現:

最後,它可能是更富有成效你看優化代碼。沒有優化,編譯器可能會做出很多似乎很奇怪的決定。代碼在優化時會更加簡潔,並且從長遠來看,您爲真實執行的代碼可能會得到優化。

+0

你所說的一切都對我很有意義,所以謝謝你的解釋。未優化的代碼讓我感到困惑,因爲我還是比較新的,但我對這些概念有一個很好的把握。 至於16字節分配,我可能是錯誤的,但我記得在C中測試sizeof(struc),它返回了16.然後我嘗試了3個int並且沒有指針的同一個結構,它是12.不管怎樣,我對於從esp中減去40的問題最爲困惑,但我認爲它是一個堆棧對齊問題,我只是還不明白。 – Awilg 2014-09-06 21:51:11