亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語(yǔ)言函數(shù)調(diào)用堆棧詳情分析

 更新時(shí)間:2022年07月14日 15:52:39   投稿:hqx  
這篇文章主要介紹了C語(yǔ)言函數(shù)調(diào)用堆棧詳情分析,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

 一、C函數(shù)棧幀開(kāi)辟以及回退過(guò)程

__cdecl(C語(yǔ)言默認(rèn)調(diào)用方式,函數(shù)參數(shù)8字節(jié)以?xún)?nèi),使用push。本節(jié)采用此方式)

main函數(shù)的棧幀調(diào)用sum函數(shù)的棧幀,sum函數(shù)棧幀使用完了以后回退都是怎么進(jìn)行的,要搞清楚這個(gè)問(wèn)題必須得看匯編代碼,匯編代碼分為兩種:inter x86(windows)和AT&T(unix)。這兩種匯編非常相似,x86的匯編是從右向左看,unix的匯編是從左向右看的。

局部變量都是通過(guò)棧底指針ebp偏移訪(fǎng)問(wèn),不生成符號(hào),不屬于數(shù)據(jù),屬于指令。

形參壓棧在C/C++中是從右向左壓棧,因?yàn)橐С挚勺冮L(zhǎng)參數(shù),如果從左向右,編譯器就不知道用戶(hù)傳入了多少實(shí)參,形參內(nèi)存是在調(diào)用函數(shù)棧幀中開(kāi)辟,每壓棧一個(gè)實(shí)參,都會(huì)開(kāi)辟一個(gè)形參的空間,棧頂指針esp都會(huì)減4字節(jié)。

實(shí)參壓棧完成后需要調(diào)用call指令來(lái)執(zhí)行sum函數(shù),執(zhí)行完sum函數(shù)后,執(zhí)行完sum函數(shù)后需要回到調(diào)用指令(call)的下一條指令繼續(xù)執(zhí)行。

call指令做兩件事:

  • 1.把下一行指令的地址入棧
  • 2.jmp跳轉(zhuǎn)

棧空間圖:

執(zhí)行call指令后,程序調(diào)到這里,不是sum函數(shù)的指令部分

在編譯階段,所有匯編指令代碼引用符號(hào)的地方全部不是合法的地址(因?yàn)槲覀儺?dāng)前文件可能引用外部的符號(hào),而編譯階段是獨(dú)立編譯的,我們鏈接的時(shí)候才會(huì)進(jìn)行符號(hào)解析、合并符號(hào)表等操作,之后再給符號(hào)分配內(nèi)存地址),對(duì)于數(shù)據(jù)符號(hào)來(lái)說(shuō)是零地址,對(duì)于函數(shù)符號(hào)來(lái)說(shuō)是-4。那么當(dāng)我們?cè)阪溄与A段符號(hào)解析完成以后,得到每一個(gè)符號(hào)的具體地址,給數(shù)據(jù)符號(hào)分配的地址是絕對(duì)地址,給函數(shù)符號(hào)分配的地址是與下一行指令地址的一個(gè)偏移量,這樣當(dāng)程序需要跳轉(zhuǎn)到某個(gè)函數(shù)地址的時(shí)候,取出PC寄存器保存的地址與該偏移量相加就得到函數(shù)的入口地址。

計(jì)算相對(duì)偏移量后就進(jìn)入了sum函數(shù),先執(zhí)行下面一段指令,才執(zhí)行我們寫(xiě)的sum函數(shù)

每次執(zhí)行一個(gè)函數(shù)前要執(zhí)行三個(gè)操作:

  • 把調(diào)用方的棧底地址入棧(push ebp),讓ebp指針指向當(dāng)前函數(shù)的棧底(mov ebp,esp)
  • 移動(dòng)棧頂指針esp,給被調(diào)用函數(shù)開(kāi)辟棧幀(sub esp 44h)
  • 初始化新棧幀內(nèi)存,把esp和ebp之間所有的棧內(nèi)存全部初始化成0xCCCCCCCC(rep stos dword ptr [edi])無(wú)效值。

Linux為棧幀不分配初始值,windows會(huì)分配初始值,為0xCCCCCCCC(-858993460)

然后執(zhí)行sum函數(shù)的指令:

局部變量通過(guò)棧底指針ebp負(fù)向偏移訪(fǎng)問(wèn),形參通過(guò)ebp正向偏移訪(fǎng)問(wèn),eax為a+b的計(jì)算結(jié)果,將計(jì)算結(jié)果賦值給temp,return的時(shí)候?qū)emp的值賦值給eax,給調(diào)用方返回

棧幀清退:

可以看到,開(kāi)辟棧幀的時(shí)候我們對(duì)占內(nèi)存進(jìn)行了初始化,但是棧幀清退的時(shí)候僅僅就是修改了esp和ebp,沒(méi)有做其他任何操作,如果我們此時(shí)通過(guò)一些手段去訪(fǎng)問(wèn)已被清退棧幀的內(nèi)存,還是可以訪(fǎng)問(wèn)到的,因?yàn)閿?shù)據(jù)還存在

參數(shù)清除:

sum函數(shù)執(zhí)行完成后,從PC寄存器中取出地址繼續(xù)執(zhí)行,這里PC寄存器存放的是call指令的下一行地址,這條指令做的操作是回退形參變量占的內(nèi)存,形參內(nèi)存由調(diào)用方開(kāi)辟和釋放。sum函數(shù)返回值由eax寄存器帶回來(lái)。

在被調(diào)用方執(zhí)行完成后,通過(guò)pop ebp就知道應(yīng)該回到哪(恢復(fù)棧底),再通過(guò)ret指令就知道回到哪以后從哪一行指令開(kāi)始運(yùn)行(取出棧頂元素放到PC寄存器里面,而棧頂元素存的就是call的下一行地址)
sum函數(shù)棧底保存的是main的棧底地址,main函數(shù)棧底保存的是調(diào)用main的函數(shù)的棧底地址

二、C函數(shù)調(diào)用約定和返回值

函數(shù)調(diào)用約定和返回值

到此這篇關(guān)于C語(yǔ)言函數(shù)調(diào)用堆棧詳情分析的文章就介紹到這了,更多相關(guān)C函數(shù)調(diào)用堆棧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 嵌入式QT移植的實(shí)現(xiàn)

    嵌入式QT移植的實(shí)現(xiàn)

    本文主要介紹了嵌入式QT移植的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • vs2019配置C++版OpenCV的方法步驟

    vs2019配置C++版OpenCV的方法步驟

    最近要用到很多OpenCV的庫(kù),所以開(kāi)始學(xué)了點(diǎn)OpenCV,本文記錄VS和OpenCV的安裝、配置過(guò)程。具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-09-09
  • C++實(shí)現(xiàn)LeetCode(82.移除有序鏈表中的重復(fù)項(xiàng)之二)

    C++實(shí)現(xiàn)LeetCode(82.移除有序鏈表中的重復(fù)項(xiàng)之二)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(82.移除有序鏈表中的重復(fù)項(xiàng)之二),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言?sizeof關(guān)鍵字的具體使用

    C語(yǔ)言?sizeof關(guān)鍵字的具體使用

    在C語(yǔ)言中,sizeof是一個(gè)非常常用的關(guān)鍵字,本文主要介紹了C語(yǔ)言?sizeof關(guān)鍵字的具體使用,包括sizeof 關(guān)鍵字的語(yǔ)法、用法、特點(diǎn)和注意事項(xiàng),感興趣的可以了解一下
    2024-02-02
  • C語(yǔ)言靜態(tài)鏈表和動(dòng)態(tài)鏈表

    C語(yǔ)言靜態(tài)鏈表和動(dòng)態(tài)鏈表

    靜態(tài)鏈表和動(dòng)態(tài)鏈表是線(xiàn)性表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)的兩種不同的表示方式。靜態(tài)鏈表的初始長(zhǎng)度一般是固定的,在做插入和刪除操作時(shí)不需要移動(dòng)元素,僅需修改指針。動(dòng)態(tài)鏈表是相對(duì)于靜態(tài)鏈表而言的,一般地,在描述線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)時(shí)如果沒(méi)有特別說(shuō)明即默認(rèn)描述的是動(dòng)態(tài)鏈表。
    2016-05-05
  • C 指針和OC 對(duì)象之間的轉(zhuǎn)換方法

    C 指針和OC 對(duì)象之間的轉(zhuǎn)換方法

    這篇文章主要給大家介紹了關(guān)于C 指針和OC 對(duì)象之間的轉(zhuǎn)換方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • C++連接數(shù)據(jù)庫(kù)SqlServer、MySql、Oracle、Access、SQLite、PostgreSQL、MongoDB、Redis

    C++連接數(shù)據(jù)庫(kù)SqlServer、MySql、Oracle、Access、SQLite、PostgreSQL、Mong

    C++是一種通用的編程語(yǔ)言,可以使用不同的庫(kù)和驅(qū)動(dòng)程序來(lái)連接各種數(shù)據(jù)庫(kù),以下是一些示例代碼,演示如何使用?C++?連接?SQL?Server、MySQL、Oracle、ACCESS、SQLite?、?PostgreSQL、MongoDB、Redis數(shù)據(jù)庫(kù)
    2024-08-08
  • 關(guān)于C++中虛擬繼承的一些總結(jié)分析

    關(guān)于C++中虛擬繼承的一些總結(jié)分析

    虛擬繼承在一般的應(yīng)用中很少用到,所以也往往被忽視,這也主要是因?yàn)樵贑++中,多重繼承是不推薦的,也并不常用
    2013-09-09
  • C++?Protobuf實(shí)現(xiàn)接口參數(shù)自動(dòng)校驗(yàn)詳解

    C++?Protobuf實(shí)現(xiàn)接口參數(shù)自動(dòng)校驗(yàn)詳解

    用C++做業(yè)務(wù)發(fā)開(kāi)的同學(xué)是否還在不厭其煩的編寫(xiě)大量if-else模塊來(lái)做接口參數(shù)校驗(yàn)?zāi)兀拷裉?,我們就模擬Java里面通過(guò)注解實(shí)現(xiàn)參數(shù)校驗(yàn)的方式來(lái)針對(duì)C++?protobuf接口實(shí)現(xiàn)一個(gè)更加方便、快捷的參數(shù)校驗(yàn)自動(dòng)工具,希望對(duì)大家有所幫助
    2023-04-04
  • C++ min/max_element 函數(shù)用法詳解

    C++ min/max_element 函數(shù)用法詳解

    這篇文章主要介紹了C++ min/max_element 函數(shù)用法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02

最新評(píng)論