C與彙編:調用子函數

研究目的:瞭解彙編如何實現C語言中的函數調用

編譯器:TDM-GCC 4.9.2 64-bit Release

反彙編:Dev-C++ 5.11


C語言代碼:

該函數調用了一個簡單的add函數,add函數將輸入的兩個參數值相加,並返回兩參數之和。


main函數:

1、2行:rbp的作用是標記基址,在一個函數的執行過程中是固定不變的,因此可藉助基址與偏移量來訪問棧內數據。rsp的作用是標識當前棧所佔空間。main函數實際上也是被調用的一方,即在第一行代碼執行前,當前rsp與rbp之間的數據爲調用方數據,需要進行保護。保護方式爲將調用函數的rbp保存進棧,以備時候恢復現場。然後讓rbp指向rsp,以便準備使用新的棧空間。我們課本上提到x86中使用32bit的esp(extended stack pointer)和ebp(extended base pointer)作爲棧指針寄存器與基址指針寄存器。然而我們的編譯器是x64的,因此使用的是64bit的rbp與rsp。

3行:rsp下移0x30,這相當於開闢了一片空間以便存儲臨時變量

4、5行:對rbp以上的地址進行操作,那部分是調用函數的變量區,將ecx、rdx保存到那裏

6行:不知用途

7、8行:對變量進行初始化,一個int變量爲4個字節,即DOUBLE WORD。

9、10行:兩變量由內存移入寄存器edx,eax

11行:eax存入ecx。至此兩變量已分別存到了ecx與edx。藉助寄存器我們可以實現函數間參數的傳遞。

12行:調用add函數

13行:返回值被存在eax中,因此需要把它取回賦給區域[rbp-0xc],即變量c

14行:eax用來存儲返回值,因此該行對應return 0語句

15行:將rsp移回到rbp處,以此釋放內存。這意味着堆棧空間的釋放不代表數據被清除。只有數據被覆蓋纔是真正的消失

16行:將rbp恢復到調用函數前的位置

17行:結束程序,返回操作系統


add函數:

1、2、3行:類似main中的操作,開闢自己的堆棧空間。

4、5行:ecx、edx寄存器中存儲了調用函數傳遞的參數,把它移到堆棧區以便進行各類運算。由於是調用函數的變量,把它存在rbp上方空餘的空間中。

6、7行:重新把變量從堆棧區取到寄存器。雖然這樣取來取去的過程顯得很傻,但當這個函數變得複雜時,這樣的操作是相當有必要的。在寄存器中運算使得運算速度加快,並且大量運算時不需要來回地取數據。

8行:計算a+b

9行:把計算結果存到局部堆棧區中

10行:將返回值寫到eax

11、12、13行:類似main中那樣,清空堆棧區後返回。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章