C語言中函數調用過程(如何管理棧空間)


ps:先做草稿,以后有時間再整理並貼圖,:)

主要是利用棧底寄存器(ebp)、棧頂寄存器(esp)跟eax寄存器(存儲返回值)來實現。

假設P調用Q:

P()

{

  Q(1,2);

}

(跟實際情況可能有點差異,主要還是用來了解函數調用的過程)

1.調用前准備,將Q的參數放到棧中(非push)

   mov $1, (%esp)

   mov $2, 4(%esp)

2.調用call 0x12345678 (Q的地址)

   首先將函數的返回地址(call語句后的那條指令的地址)進棧,

   然后跳到0x12345678執行Q的代碼。

3.將舊的ebp進棧(用於退出Q時還原)

   push %ebp

4.設置新的棧底

   mov %esp, %ebp

5.為Q分配棧空間(棧是向下生長的)

   sub $24, %esp    (16 * k + 8,用於對齊)

6.執行Q的相關代碼。局部變量/參數是根據esp、ebp跟偏移量來進行存取的。

7.函數離開前將返回值賦值給%eax。

8.調用leave,相當於:

   mov %ebp, %esp (還原棧頂)

   pop %ebp (還原棧底)

9.處理返回值並接着P接着的代碼繼續執行。

 

貼多一張Linux運行時存儲器映像的圖

.text   代碼段

.rodata   存儲字符串常量

.data  存儲已初始化的全局/靜態變量

.bss    存儲為初始化/初始化為0的全局/靜態變量(在可執行文件中只占一個占位符,程序加載的時候才分配空間)

 

ELF文件中有.rel.text/.rel.data段,用於重定位。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM