2011-04-11 39 views
3

我是一個學習裝配的新人。我寫了一個C文件:我有關於堆棧幀結構的問題嗎?

#include <stdlib.h> 

int max(int c) 
{ 
     int d; 
     d = c + 1; 

     return d; 
} 

int main(void) 
{ 
     int a = 0; 
     int b; 
     b = max(a); 

     return 0; 
} 

和我使用gcc -S as01.c並創建一個彙編文件。

 .file "as01.c" 
     .text 
.globl max 
     .type max, @function 
max: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $32, %esp 
     movl $0, -4(%ebp) 
     movl $1, -24(%ebp) 
     movl $2, -20(%ebp) 
     movl $3, -16(%ebp) 
     movl $4, -12(%ebp) 
     movl $6, -8(%ebp) 
     movl 8(%ebp), %eax 
     addl $1, %eax 
     movl %eax, -4(%ebp) 
     movl -4(%ebp), %eax 
     leave 
     ret 
     .size max, .-max 
.globl main 
     .type main, @function 
main: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $20, %esp 
     movl $0, -4(%ebp) 
     movl -4(%ebp), %eax 
     movl %eax, (%esp) 
     call max 
     movl %eax, -8(%ebp) 
"as01.s" 38L, 638C   

I」相混淆,怎麼一回事,因爲在movl %eax, -4(%ebp) movl -4(%ebp), %eax MAX(), 我知道,%eax中用於返回任何函數的值。 我認爲%eax是臨時註冊商店c + 1。 這是對的? 感謝您的回答。

+1

你的平臺是什麼?當提出關於程序集的問題時,我想你最好讓我們知道你的操作系統和編譯器。你在使用64位平臺嗎? – 2011-04-11 12:31:55

+4

當使用'gcc -S'來查看彙編輸出時,強烈建議使用'-Os'。 Unoptimised彙編程序是非常詳細和充滿無用的垃圾。相反,優化的彙編器更易於閱讀。 – 2011-04-11 12:46:46

回答

4

您沒有打開優化,所以編譯器生成的代碼非常糟糕。所有值的主存儲位於堆棧幀中,並且只有足夠長的時間才能將值加載到寄存器中進行計算。

的代碼實際上分解成:

pushl %ebp 
    movl %esp, %ebp 
    subl $32, %esp 

標準函數序言,建立一個新的堆棧幀,並保留堆棧幀50個字節。

movl $0, -4(%ebp) 
    movl $1, -24(%ebp) 
    movl $2, -20(%ebp) 
    movl $3, -16(%ebp) 
    movl $4, -12(%ebp) 
    movl $6, -8(%ebp) 

用虛擬值填充堆棧幀(大概是作爲調試幫助)。

movl 8(%ebp), %eax 
    addl $1, %eax 
    movl %eax, -4(%ebp) 

從堆棧幀中讀取參數c,添加一個參數,將其存儲到一個(不同的)堆棧槽中。

movl -4(%ebp), %eax 
    leave 
    ret 

讀取堆棧槽中的值並將其返回。

如果您通過優化編譯,您會看到大部分代碼都消失了。如果你使用-fomit-frame-pointer -Os,您應該結束了與此:

max: 
    movl 4(%esp), %eax 
    incl %eax 
    ret 
0
movl %eax, -4(%ebp) 

這裏計算了d(現藏eax)的值保存在d的存儲單元。

movl -4(%ebp), %eax 

雖然這裏的返回值(D的)被加載到eax,因爲,如你所知,eax保持功能的返回值。
正如@David所說的,你正在編譯時沒有進行優化,所以gcc生成易於調試的代碼,這有時是非常低效和重複的。