網站首頁 編程語言 正文
什么是函數棧幀
我們在寫C語言代碼的時候,經常會把一個獨立的功能抽象為函數,所以C程序是以函數為基本單位的。
那函數是如何調用的?函數的返回值又是如何待會的?函數參數是如何傳遞的?這些問題都和函數棧幀有關系。
函數棧幀(stack frame)就是函數調用過程中在程序的調用棧(call stack)所開辟的空間,這些空間是用來存放:
- 函數參數和函數返回值
- 臨時變量(包括函數的非靜態的局部變量以及編譯器自動生產的其他臨時變量)
- 保存上下文信息(包括在函數調用前后需要保持不變的寄存器)。
什么是棧?
棧(stack)是現代計算機程序里最為重要的概念之一,幾乎每一個程序都使用了棧,沒有棧就沒有函 數,沒有局部變量,也就沒有我們如今看到的所有的計算機語言。
與函數棧幀有關的匯編語句
eax:通用寄存器,保留臨時數據,常用于返回值
ebx:通用寄存器,保留臨時數據
ebp:棧底寄存器
esp:棧頂寄存器
eip:指令寄存器,保存當前指令的下一條指令的地址
mov:數據轉移指令
push:數據入棧,同時esp棧頂寄存器也要發生改變
pop:數據彈出至指定位置,同時esp棧頂寄存器也要發生改變
sub:減法命令
add:加法命令
call:函數調用,1. 壓入返回地址 2. 轉入目標函數
jump:通過修改eip,轉入目標函數,進行調用
ret:恢復返回地址,壓入eip,類似pop eip命令(返回子程序)
函數如何創建棧幀并銷毀
當程序進入main函數時,要給main函數在棧區創建空間,esp(棧頂)和ebp(棧底)對main函數進行維護
當程序執行時,我們在調試窗口對堆棧段進行調用,我們可以看到main函數是被__tmainSRTStartup函數所調用,說明main函數是它的內部函數,而__tmainSRTStartup又是被mainCRStartup這個函數調用
梳理一下上面的思路
這些函數在堆棧當中的存儲
main函數棧幀開辟
接下來重新調試,我們轉到反匯編
調用main函數之前,esp和ebp對調用main函數的函數進行維護 ,當棧頂發生改變時,esp會指向新的棧頂
003118B0 push ebp
003118B1 mov ebp,esp
先把ebp入棧,然后把ebp移動到esp的位置
003118B3 sub esp,0E4h
003118B9 push ebx
003118BA push esi
003118BB push edi
之后又把esp往上移動,移動完把ebx,esi,edi壓棧,esp和ebp現在指的這塊空間是為main函數預先開辟好的
把edi-0EFH也就是main函數開始的這里的地址,放到edi里面去,然后從這個地址開始賦值39次的雙字節數據,賦值為CCCC
到這里main函數棧幀開辟完成
接下來就是在main函數的空間里,創建三個變量,并給賦值
調用Add函數
對函數進行傳參,創建倆個臨時變量,然后壓棧進去
接下來進入call開始調用函數call此時的地址是00C2144B
此時按下F11,我們發現call指令的下一條地址被壓到了棧區
把call的下一個地址壓棧,ps:后面會用到這條指令,可先放在這不管
接下來進入Add函數,跟前面main函數一樣,先開辟空間,然后賦值為CCCCCC,再為變量在函數里創建空間并賦值
接下來執行加法運算,由于剛才已經創建好了零時變量,所以把他倆進行相加,加完之后把結果傳過來就行,傳過來之后把這個值放在eax里面去
返回主函數
按順序出棧,之后把ebp賦值給esp
之后pop,ebp把ebp進行出棧,ebp便回到main函數這里,ebp此時回到這里,esp也自然而然的往下指一個,ret指令是返回,然后esp來到了call指令的下一條指令
把棧頂指針彈出去,esp自然向下指一條
之后給esp加8即釋放這倆個臨時變量
之后把eax放到ebp-20h,eax是存放剛才加法和的地方
原文鏈接:https://blog.csdn.net/weixin_49449676/article/details/124508436
相關推薦
- 2022-10-08 C#在新建線程中使用Timer無效問題及解決_C#教程
- 2022-06-06 typescript中的泛型(genericParadigm)、interface、extends、
- 2022-02-11 Command line is too long. Shorten command line for
- 2023-03-27 Go語言實現的可讀性更高的并發神庫詳解_Golang
- 2023-03-26 spring?boot整合redis中間件與熱部署實現代碼_Redis
- 2022-05-21 C語言實現會員管理系統_C 語言
- 2022-12-24 C語言中的逗號運算符詳解_C 語言
- 2022-11-07 python中openpyxl庫用法詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支