從彙編看c語言函數調用

來源:互聯網
上載者:User

      學C語言時,就聽老師說函數調用時是通過棧來記錄資訊,又聽說什麼“保留現場”,"恢複現場"一些既聽不懂,也不知道怎麼弄懂的東西。最近正在學習Linux下的彙編,現在就通過一個簡單的例子來展示一下彙編級的函數調用,這樣能夠增加大家對C語言的理解。雖然並不是很完善,但是足夠闡明函數調用的思想。

在Linux下通過命令gcc -S functest.c,可以產生組譯工具functest.s

//functest.c

#include <stdio.h>

void func(int a, int b)

{

    int c;

    int d;

    c = a;

    d = b;

}

int main()

{

    func(2, 3);

    return 0;

}

在Linux下通過命令gcc -S functest.c,可以產生組譯工具functest.s

     首先可以看到一點,一個簡單的C程式的彙編卻是如此之長,可以想到良好的程式書寫習慣有多大的好處。

     言歸正傳,我們不分析每條指令都是什麼意思,我們重點看函數調用那一部分。

我們注意在調用call func之前,第25,26,27行是為func準備參數。首先把%esp減去8個位元組,這是因為在Linux中int型為4個位元組(想想譚浩強C語言程式設計書中說int為2個位元組?這東西依賴於具體的作業系統和編譯器),即手動修改棧指標,可以發現C語言中函數參數是儲存在棧中的,進一步,我們發現gcc把3先壓入棧中,之後是2,可以說明,C中函數參數的壓棧順序和函數書寫順序正好相反。執行完這3條指令後,棧中的內容如下:

之後28行調用func,通過call指令。執行call指令時,不僅僅去調用func函數,而且做了一個我們程式員看不到的動作,就是把下一條指令的地址壓入到棧中。這點我們稍後會講到,而且從這我們也能略窺到,函數名只不過是地址的別名,只不過是為了方便程式員理解,我們可以完全用16進位地址取代這些別名,當然電腦並不覺得用地址比用別名更困難。

      現在我們進入func。6,7行的兩條指令可以認為是套路,具體原因可以見[注1]。先把%ebp的值壓入棧,之後把棧頂賦給%ebp,隱約我們可以猜到,因為在這裡修改了%ebp,而又不想原來的%ebp被覆蓋,那麼只好先把原來的%ebp儲存到棧中,必要的時候可以在棧中恢複原來的%ebp。第8行,將棧頂向下移,這個操作的目的是為函數中的臨時變數在棧中分配儲存空間。有人會想為什麼不用其它的記憶體或者寄存器去儲存臨時變數?這是因為如果為大型項目編寫程式,要跟蹤哪些變數使用記憶體,而哪些使用寄存器簡直就是惡夢,所以C中用棧儲存臨時變數,因為在棧在函數調用後會釋放或者清空,那麼這些變數是不可能被其它函數所調用,故這也是“局部變數”的由來。這個行為也使程式員在函數中要對操作得非常小心,例如我們在函數中開了一個很大的數組,那麼在為這個數組開闢棧空間時,很可能出現段錯誤。執行完6,7,8三行後,棧中的內容如下:

9,10行是把3賦值給d,11,12是把2賦值給c。那麼棧中的內容確定下來如下:

      可以看到,有兩個為局部變數開闢的占空間實際並沒有被使用到。

      有人現在有疑問那個標記”XXXX”的單元式幹什麼用的,現在我來告訴你那個其實就是函數的返回地址,記得我前面說過,call指令會把調用函數後的下一條指令地址入棧,那麼那個地址就存在XXXX那個單元中,這樣執行完函數時可以根據棧中的這個地址返回到主調用程式,繼續運行。那麼完整的棧內容如下:

這樣函數基本執行完畢,leave是恢複調用func之前的棧內容和%ebp內容,完全可以用以下指令替代:

movl %ebp, %esp

popl %ebp

 

ret 指令就是返回到主程式,不贅述。

30行為主程式中從棧中刪除調用func時的參數2,3。

 

      這樣一個函數的完整調用過程就給大家展示完了,希望對大家有所協助。本人剛學彙編,如有錯誤,還望大家指出。

 

注1:這樣做,是為了對函數參數容易進行讀取。在設計之初,考慮到用根據%esp和位移量來對棧中的參數進行訪問,但是由於在函數中%esp極有可能改變,那麼維護這個位移量也變的複雜,所以利用%ebp記錄進入函數時棧指標的位置,而%ebp在這個函數中不會被改變,那麼通過%ebp去定位函數參數就變的非常容易,所以一般有人把%ebp也稱為棧底指標,而這也成為了組譯工具員的習慣。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.