網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷(xiāo)毀原理圖解_C 語(yǔ)言
作者:頭發(fā)沒(méi)有代碼多 ? 更新時(shí)間: 2022-07-15 編程語(yǔ)言什么是函數(shù)棧幀
我們?cè)趯?xiě)C語(yǔ)言代碼的時(shí)候,經(jīng)常會(huì)把一個(gè)獨(dú)立的功能抽象為函數(shù),所以C程序是以函數(shù)為基本單位的。
那函數(shù)是如何調(diào)用的?函數(shù)的返回值又是如何待會(huì)的?函數(shù)參數(shù)是如何傳遞的?這些問(wèn)題都和函數(shù)棧幀有關(guān)系。
函數(shù)棧幀(stack frame)就是函數(shù)調(diào)用過(guò)程中在程序的調(diào)用棧(call stack)所開(kāi)辟的空間,這些空間是用來(lái)存放:
- 函數(shù)參數(shù)和函數(shù)返回值
- 臨時(shí)變量(包括函數(shù)的非靜態(tài)的局部變量以及編譯器自動(dòng)生產(chǎn)的其他臨時(shí)變量)
- 保存上下文信息(包括在函數(shù)調(diào)用前后需要保持不變的寄存器)。
什么是棧?
棧(stack)是現(xiàn)代計(jì)算機(jī)程序里最為重要的概念之一,幾乎每一個(gè)程序都使用了棧,沒(méi)有棧就沒(méi)有函 數(shù),沒(méi)有局部變量,也就沒(méi)有我們?nèi)缃窨吹降乃械挠?jì)算機(jī)語(yǔ)言。
與函數(shù)棧幀有關(guān)的匯編語(yǔ)句
eax:通用寄存器,保留臨時(shí)數(shù)據(jù),常用于返回值
ebx:通用寄存器,保留臨時(shí)數(shù)據(jù)
ebp:棧底寄存器
esp:棧頂寄存器
eip:指令寄存器,保存當(dāng)前指令的下一條指令的地址
mov:數(shù)據(jù)轉(zhuǎn)移指令
push:數(shù)據(jù)入棧,同時(shí)esp棧頂寄存器也要發(fā)生改變
pop:數(shù)據(jù)彈出至指定位置,同時(shí)esp棧頂寄存器也要發(fā)生改變
sub:減法命令
add:加法命令
call:函數(shù)調(diào)用,1. 壓入返回地址 2. 轉(zhuǎn)入目標(biāo)函數(shù)
jump:通過(guò)修改eip,轉(zhuǎn)入目標(biāo)函數(shù),進(jìn)行調(diào)用
ret:恢復(fù)返回地址,壓入eip,類(lèi)似pop eip命令(返回子程序)
函數(shù)如何創(chuàng)建棧幀并銷(xiāo)毀
當(dāng)程序進(jìn)入main函數(shù)時(shí),要給main函數(shù)在棧區(qū)創(chuàng)建空間,esp(棧頂)和ebp(棧底)對(duì)main函數(shù)進(jìn)行維護(hù)
當(dāng)程序執(zhí)行時(shí),我們?cè)谡{(diào)試窗口對(duì)堆棧段進(jìn)行調(diào)用,我們可以看到main函數(shù)是被__tmainSRTStartup函數(shù)所調(diào)用,說(shuō)明main函數(shù)是它的內(nèi)部函數(shù),而__tmainSRTStartup又是被mainCRStartup這個(gè)函數(shù)調(diào)用
梳理一下上面的思路
這些函數(shù)在堆棧當(dāng)中的存儲(chǔ)
main函數(shù)棧幀開(kāi)辟
接下來(lái)重新調(diào)試,我們轉(zhuǎn)到反匯編
調(diào)用main函數(shù)之前,esp和ebp對(duì)調(diào)用main函數(shù)的函數(shù)進(jìn)行維護(hù) ,當(dāng)棧頂發(fā)生改變時(shí),esp會(huì)指向新的棧頂
003118B0 push ebp
003118B1 mov ebp,esp
先把ebp入棧,然后把ebp移動(dòng)到esp的位置
003118B3 sub esp,0E4h
003118B9 push ebx
003118BA push esi
003118BB push edi
之后又把esp往上移動(dòng),移動(dòng)完把ebx,esi,edi壓棧,esp和ebp現(xiàn)在指的這塊空間是為main函數(shù)預(yù)先開(kāi)辟好的
把edi-0EFH也就是main函數(shù)開(kāi)始的這里的地址,放到edi里面去,然后從這個(gè)地址開(kāi)始賦值39次的雙字節(jié)數(shù)據(jù),賦值為CCCC
到這里main函數(shù)棧幀開(kāi)辟完成
接下來(lái)就是在main函數(shù)的空間里,創(chuàng)建三個(gè)變量,并給賦值
調(diào)用Add函數(shù)
對(duì)函數(shù)進(jìn)行傳參,創(chuàng)建倆個(gè)臨時(shí)變量,然后壓棧進(jìn)去
接下來(lái)進(jìn)入call開(kāi)始調(diào)用函數(shù)call此時(shí)的地址是00C2144B
此時(shí)按下F11,我們發(fā)現(xiàn)call指令的下一條地址被壓到了棧區(qū)
把call的下一個(gè)地址壓棧,ps:后面會(huì)用到這條指令,可先放在這不管
接下來(lái)進(jìn)入Add函數(shù),跟前面main函數(shù)一樣,先開(kāi)辟空間,然后賦值為CCCCCC,再為變量在函數(shù)里創(chuàng)建空間并賦值
接下來(lái)執(zhí)行加法運(yùn)算,由于剛才已經(jīng)創(chuàng)建好了零時(shí)變量,所以把他倆進(jìn)行相加,加完之后把結(jié)果傳過(guò)來(lái)就行,傳過(guò)來(lái)之后把這個(gè)值放在eax里面去
返回主函數(shù)
按順序出棧,之后把ebp賦值給esp
之后pop,ebp把ebp進(jìn)行出棧,ebp便回到main函數(shù)這里,ebp此時(shí)回到這里,esp也自然而然的往下指一個(gè),ret指令是返回,然后esp來(lái)到了call指令的下一條指令
把棧頂指針彈出去,esp自然向下指一條
之后給esp加8即釋放這倆個(gè)臨時(shí)變量
之后把eax放到ebp-20h,eax是存放剛才加法和的地方
原文鏈接:https://blog.csdn.net/weixin_49449676/article/details/124508436
相關(guān)推薦
- 2022-07-29 Django?狀態(tài)保持搭配與存儲(chǔ)的實(shí)現(xiàn)_python
- 2023-06-21 Python中sorted()用法案例代碼_python
- 2022-05-21 Deployment副本無(wú)狀態(tài)服務(wù)創(chuàng)建及水平擴(kuò)展_服務(wù)器其它
- 2022-12-09 Flutter?Widgets?MediaQuery控件屏幕信息適配_IOS
- 2022-10-19 C#實(shí)現(xiàn)自動(dòng)生成電子印章_C#教程
- 2022-06-10 ASP.NET?Core使用EF查詢數(shù)據(jù)_實(shí)用技巧
- 2022-08-07 pd.drop_duplicates刪除重復(fù)行的方法實(shí)現(xiàn)_python
- 2022-07-24 .Net創(chuàng)建型設(shè)計(jì)模式之建造者、生成器模式(Builder)_基礎(chǔ)應(yīng)用
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支