習慣高階語言開發時,幾行代碼便能完成複雜運算。但這些代碼究竟如何在電腦中存儲與運行?本文以 C 語言遞歸範例為切入點,帶你深入理解程式執行的底層機制——代碼段、數據段、堆疊幀、基址指標(EBP)與堆疊指標(ESP)的協作。
#include <stdio.h>
int recursiveFun(int i) {
if (i < 1) return recursiveFun(i + 1);
else return i;
}
int fun() {
int i = 0;
i = recursiveFun(i);
return i;
}
int main() {
int i;
i = fun();
printf("%d", i);
}
程式編譯後,機器指令存放在代碼段。以 VC++ 反組譯觀察,`main` 函數入口地址為 0x002a1490,該記憶體單元儲存的機器指令為 55(對應 `push ebp`)。
未顯式申請堆記憶體時,區域變數、返回地址等存放在堆疊中,形成活動記錄。函數巢狀調用對應堆疊的壓入與彈出。兩個關鍵暫存器:
每個函數入口處,EBP 所指記憶體單元存放的是呼叫該函數的上一層函數的 EBP 值。透過這條鏈,函數返回時能找回呼叫者上下文,繼續執行。
實測觀察:
0x0022fec8,該位置存值 0x0022ff18(main 的 EBP)0x0022fde8,存值 0x0022fec8(上一層 EBP)這樣的鏈結構確保了函數返回後能正確恢復現場。
本文建立了靜態視角的認知,下一篇將動態演示堆疊在遞歸調用過程中的壓入、彈出細節,並解析參數傳遞、返回值處理等機制。