2014-09-30 38 views
0

僅僅爲了我的好奇心,我正在研究傳遞給函數的值實際上是如何由被調用函數操作的。爲了明確我的疑問,我理解編譯器爲c代碼生成一個代碼,然後順序編譯它(如果我錯了,請更正)。我懷疑在被調用函數中如何訪問參數值?我的意思是參數必須是調用函數的一部分(就像我給出的例子中的main())。編譯器如何安排在調用函數中傳遞的值與在被調用函數中訪問的值相同。爲了使我的觀點清楚,請看下面的代碼:調試相當於c代碼的程序集以瞭解函數調用

#include <stdio.h> 

void check(int); 

int main() 
{ 
    check(9999); 
} 

void check(int a) 
{ 
    int b; 
    b = a; 
} 

在上面的代碼的代碼執行的b = 9999值之後;但函數check()中的a的值在彙編級別達到9999的值時,如何從main()調用函數check()。它是否像參數存儲在某些寄存器中,並使用check()中的那些寄存器進行相應訪問?我希望你能理解我的問題。

+0

要求編譯器輸出彙編代碼(例如'gcc -fverbose-asm -S')。請注意,編譯器可以將'check'函數優化爲'nop' – 2014-09-30 08:30:18

+0

參數傳遞給函數的方式可能會有所不同(因爲編譯器優化和調用約定)。開始你可以閱讀[這篇文章](http://en.wikipedia.org/wiki/X86_calling_conventions)。 – 2014-09-30 08:32:07

+0

通常情況下(取決於操作系統和編譯器)傳遞的是「a」的地址,偶爾學術編譯器會傳遞「a」副本的地址,因爲它嚴格按值傳遞,但幾乎總是進行優化遠。 – 2014-09-30 08:33:53

回答

4

calling conventions取決於ABI和目標處理器(爲您的編譯器)。

x86 calling convention上有一個Wikipipage。在Linux上,您應該閱讀x86-64 ABI。 (您的a正式參數check通過寄存器傳遞)。

編譯器允許optimizechecknop(因爲它的參數a有沒有明顯的效果)

閱讀也WIKIPAGE上evaluation strategy:C語言編程需要的call-by-值語義。

考慮(如果使用GCC)與gcc -fverbose-asm -S編譯(或許也與優化像-O2選項),並期待產生*.s彙編代碼裏面。

+1

感謝-fverbose-asm選項 – 2014-09-30 08:56:27

0

您可以使用gcc -S source.cgcc -S source.c -O2這兩個命令都會生成彙編代碼,但是第一個命令會生成沒有優化的代碼,並且參數會通過堆棧,然後是第2個參數,並進行優化,參數將被傳遞寄存器