最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷(xiāo)毀原理圖解

 更新時(shí)間:2022年05月20日 08:42:16   作者:頭發(fā)沒(méi)有代碼多  
我們知道c語(yǔ)言中函數(shù)都是被調(diào)用的,main函數(shù)里面能調(diào)用其他函數(shù),其實(shí)main函數(shù)也是被別的函數(shù)調(diào)用的,下面通過(guò)本文給大家分享c語(yǔ)言函數(shù)棧幀的創(chuàng)建和銷(xiāo)毀過(guò)程,一起看看吧

什么是函數(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是存放剛才加法和的地方

到此這篇關(guān)于C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷(xiāo)毀原理圖解的文章就介紹到這了,更多相關(guān)C語(yǔ)言函數(shù)棧幀內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)圖的創(chuàng)建與遍歷實(shí)驗(yàn)示例

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)圖的創(chuàng)建與遍歷實(shí)驗(yàn)示例

    這篇文章主要為大家介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)圖的創(chuàng)建與遍歷實(shí)驗(yàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • C語(yǔ)言 數(shù)與串之間轉(zhuǎn)換的方法

    C語(yǔ)言 數(shù)與串之間轉(zhuǎn)換的方法

    C語(yǔ)言 數(shù)與串之間轉(zhuǎn)換的方法,需要的朋友可以參考一下
    2013-05-05
  • C++實(shí)現(xiàn)職工工資管理系統(tǒng)

    C++實(shí)現(xiàn)職工工資管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單的職工工資管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 詳解C++中future和promise的使用

    詳解C++中future和promise的使用

    future和promise的作用是在不同線程之間傳遞數(shù)據(jù),這篇文章主要為大家詳細(xì)介紹了C++中future和promise的具體使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-05-05
  • 解析鴻蒙輕內(nèi)核靜態(tài)內(nèi)存的使用

    解析鴻蒙輕內(nèi)核靜態(tài)內(nèi)存的使用

    摘要:靜態(tài)內(nèi)存實(shí)質(zhì)上是一個(gè)靜態(tài)數(shù)組,靜態(tài)內(nèi)存池內(nèi)的塊大小在初始化時(shí)設(shè)定,初始化后塊大小不可變更。靜態(tài)內(nèi)存池由一個(gè)控制塊和若干相同大小的內(nèi)存塊構(gòu)成。控制塊位于內(nèi)存池頭部,用于內(nèi)存塊管理。內(nèi)存塊的申請(qǐng)和釋放以塊大小為粒度
    2021-06-06
  • C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[八]

    C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[八]

    C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[八]...
    2007-02-02
  • 使用C++實(shí)現(xiàn)監(jiān)控文件是否被修改

    使用C++實(shí)現(xiàn)監(jiān)控文件是否被修改

    軟件開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)用到配置文件,某些應(yīng)用場(chǎng)景要求在軟件運(yùn)行時(shí)動(dòng)態(tài)修改配置文件,此時(shí)就需要監(jiān)控配置文件是否被修改,下面我們就來(lái)看看如何使用C++實(shí)現(xiàn)這一功能吧
    2024-02-02
  • C++從序列容器中刪除元素的四種方法

    C++從序列容器中刪除元素的四種方法

    刪除元素的方法在序列容器和關(guān)聯(lián)容器之間是非常不同的,在序列容器中,vector 和 string 是最常用的,但這里也會(huì)介紹 deque 和 list 以供全面了解,盡管在一般情況下可能不會(huì)使用它們,本文將詳細(xì)給大家介紹一下C++從序列容器中刪除元素的四種方法,需要的朋友可以參考下
    2025-03-03
  • C++線程池實(shí)現(xiàn)

    C++線程池實(shí)現(xiàn)

    線程池是一種并發(fā)編程技術(shù),通過(guò)預(yù)先創(chuàng)建一組線程并復(fù)用它們來(lái)執(zhí)行多個(gè)任務(wù),避免了頻繁創(chuàng)建和銷(xiāo)毀線程的開(kāi)銷(xiāo),本文就來(lái)介紹一下C++線程池實(shí)現(xiàn),感興趣的可以了解一下
    2025-02-02
  • C++中回調(diào)函數(shù)(CallBack)的用法分析

    C++中回調(diào)函數(shù)(CallBack)的用法分析

    這篇文章主要介紹了C++中回調(diào)函數(shù)(CallBack)的用法,較為詳細(xì)的分析了C++中回調(diào)函數(shù)(CallBack)的原理并以實(shí)例形式總結(jié)了其具體用法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01

最新評(píng)論

许昌县| 宜都市| 麻栗坡县| 醴陵市| 神木县| 辽中县| 田林县| 马公市| 四子王旗| 聊城市| 普洱| 肇州县| 惠州市| 峨眉山市| 鲜城| 新化县| 忻城县| 宝丰县| 虞城县| 垦利县| 青田县| 哈尔滨市| 绍兴县| 永定县| 玉环县| 青海省| 丹寨县| 封开县| 吉木乃县| 房产| 潼关县| 安陆市| 措勤县| 南康市| 峨眉山市| 博野县| 蓬莱市| 蒲江县| 五河县| 鄂温| 繁峙县|