目錄
- 1.棧幀
- 1.進程地址空間
- 2.棧幀說明
- 2.認識相關寄存器
- 3.認識相關匯編命令
- 4.過程理解
- 5.棧幀總結
- 6.補充
1.棧幀
1.進程地址空間
.進程地址空間
2.棧幀說明
- 調用函數,形成棧幀
- 函數返回,釋放棧幀
- 局部變量是存放在棧區上的
- 棧區內存的使用習慣是:
- 先使用高地址空間,再使用低地址空間
- 如:數組隨著下標的增長,地址是由低到高變化的
2.認識相關寄存器
eax
:通用寄存器,保留臨時數據,常用于返回值ebx
:通用寄存器,保留臨時數據ebp
:棧底寄存器esp
:棧頂寄存器eip
:指令寄存器,保存當前指令的下一條指令的地址
3.認識相關匯編命令
mov
:數據轉移指令push
:數據入棧,同時esp
棧頂寄存器也要發生改變pop
:數據彈出至指定位置,同時esp棧頂寄存器也要發生改變sub
:減法命令add
:加法命令call
:函數調用,1. 壓入返回地址 2. 轉入目標函數- 將當前指令的下一條指令入棧(push到棧中,影響ESP)
- 跳轉到目標函數起始地址處運行(修改EIP,到達目標函數)
jump
:通過修改eip
,轉入目標函數,進行調用ret
:恢復返回地址,壓入eip
,類似pop eip
命令
4.過程理解
-
起步,
main()
也是要被調用的
-
main()
也要形成棧幀結構
-
起步
-
開始調用
-
調用
call
前
-
調用
call
后
-
整體圖解
-
-
形成棧幀
-
釋放棧幀
-
釋放臨時拷貝,徹底釋放空間
5.棧幀總結
- 調用函數,需要先形成臨時拷貝,形成過程是從右向左的
- 臨時空間的開辟,是在對應函數棧幀內部開辟的
- 函數調用完畢,棧幀結構被釋放掉
- 臨時變量具有臨時性的本質:棧幀具有臨時性
- 調用函數是有成本的,成本體現在時間和空間上,本質是形成和釋放棧幀有成本
- 函數調用,因拷貝所形成的臨時變量,變量和變量之間的位置關系是有規律的(地址連續)
6.補充
- 堆上都是動態分配,做不到靜態分配
- 棧既可以靜態分配,也可以動態分配
- 靜態分配 – 在函數體中創建了一個變量
- 動態分配
- 頭文件
<malloc.h>
下,有一個void* __cdecl alloca(size_t)
- 作用與malloc等類似,但是它申請的是“棧(stack)”空間的內存
- 用完會在退出棧時自動釋放,無需手動釋放
- 頭文件