主頁 >  其他 > 函式呼叫堆疊的一些簡單認識

函式呼叫堆疊的一些簡單認識

2023-05-04 08:01:36 其他

   程式的執行可以理解為連續的函式呼叫,每一個用戶態(用戶態指的是CPU指令集權限ring 0,用戶只能訪問常用CPU指令集,在應用程式中運行)行程都對應一個呼叫堆疊結構,當一個函式執行完畢后,會自動回到原先呼叫函式的位置(call指令)的下一步命令并執行,堆疊結構的作用是保存函式回傳地址、傳遞函式引數、記錄本地變數、臨時保存函式背景關系(背景關系,也就是執行函式所需要的相關資訊),

       暫存器:

      暫存器分配:

      暫存器是處理器加工資料和運行程式的重要載體,暫存器在程式執行中中負責存盤資料和指令,因此函式呼叫與暫存器有重要聯系,

  32位CPU所含有的暫存器有:

    8個32位通用暫存器,其中包含4個資料暫存器(EAX、EBX、ECX、EDX)、2個變址暫存器(ESI和EDI)和2個指標暫存器(ESP和EBP)
    6個段暫存器(ES、CS、SS、DS、FS、GS)
    1個指令指標暫存器(EIP)
    1個標志暫存器(EFLAGS)
  最初的8086平臺使用16位暫存器,每個暫存器都有具體特定的用途,但隨著32位暫存器的出現,32位暫存器采用平臺尋址方式,因此對特殊暫存器沒有過多要求,但由于歷史原因,16位暫存器的名字被保存,EAX,EBX,ECX,EDX,ESI,EDI這六個暫存器通常作為通用暫存器使用,但是部分指令會有特定的源暫存器或者目的暫存器(比如%eax通常用于保存函式回傳值),因此為避免兼容性問題,ABI規范各個暫存器的作用,EAX通常用于保存函式回傳值,EBX用于存盤基地址,ECX是計數器,重復前綴指令(REP,X86匯編指令,使指定指令重復n次,但只能指定一條陳述句)和LOOP指令(回圈指令,能夠執行代碼塊)的內定計數器,回圈重復執行次數將保留在cx中,EDX一般用來儲存整數除法中的余數部分(當函式體中包含除法時,EAX保留整數部分,EDX則負責保存余數部分,乘除關系一般都與EAX、EDX有關),而EDI、ESI則通常用于儲存函式引數

  EIP指令暫存器通常指向下一條待執行的指令地址(代碼段內的偏移量),每完成一潭訓編指令,EIP的值就會增加,ESP指向當前函式的堆疊幀結構的堆疊頂位置,EBP則始終指向當前函式的堆疊幀結構的堆疊底位置,同時注意EIP暫存器不能通過尋常方式訪問到(無法獲得opcode)

     在Intel  CPU中,通常將EBP暫存器作為堆疊幀指標暫存器,存盤基地址,對于函式引數,偏移量為正值,對于區域變數,偏移量為負值

  暫存器的使用原則:

     主調函式指的是呼叫其他函式的函式,被調函式指的是被其他函式呼叫的函式

    主調函式一般使用eax、ecx、edx暫存器作為主調函式保存暫存器,當函式呼叫時,若主調函式希望保持這些暫存器的值,則必須在呼叫前顯式地將其保存在堆疊中;被調函式可以覆寫這些暫存器,而不會破壞主調函式所需的資料,被調函式一般使用ebx、edi、esi作為被調函式保存暫存器,被調函式在覆寫這些暫存器的值時,必須先將暫存器原值壓入堆疊中保存起來,并在函式回傳前從堆疊中恢復其原值,因為主調函式可能也在使用這些暫存器,此外,被調函式必須保持暫存器%ebp和%esp,并在函式回傳后將其恢復到呼叫前的值,亦即必須恢復主調函式的堆疊幀

  堆疊幀結構:

   函式的呼叫通常是嵌套的,在同一時刻,堆疊中會有多個函式的資訊,每一個未執行完成的函式都有一個連續獨立的區域即堆疊幀,堆疊幀是堆疊的一個邏輯片段,當函式呼叫時,邏輯堆疊幀被壓入堆疊中,當函式回傳時,堆疊幀從堆疊中彈出,堆疊幀主要儲存函式引數、函式內區域變數以及回傳前一堆疊幀所需要的資訊

          堆疊幀的作用:

         1、保存主調函式的區域變數

   2、向被調函式傳遞引數

   3、回傳被調函式的回傳值

   4、回傳函式的回傳地址(即當被呼叫函式執行完成時應當執行的下一條指令)

   堆疊幀的邊界由堆疊幀基暫存器EBP和堆疊頂暫存器ESP來界定,EBP位于堆疊底,高地址,在堆疊幀內位置固定,ESP位于堆疊頂,低地址,位置隨著出堆疊和入堆疊而發生變化,因而資料訪問通常通過EBP來進行(通過偏移量來訪問)

          ESP指向堆疊頂,EBP一般指向堆疊幀的開始位置

   現在在假定有一個程式:A()——>B()——>C()

   那么A中元素包括A函式的區域變數,傳給函式B的引數、B函式的回傳值、執行完B的下一條指令的地址

                  B中元素包括B函式的區域變數、傳給函式C的引數、C函式的回傳值、執行完C的下一條指令的地址

     C中元素包括C函式的區域變數

因此:

         (1)被調函式的引數和回傳值保存在主調函式的堆疊幀中

    (2)以堆疊幀為單位,那么C函式堆疊幀位于堆疊頂,ESP暫存器指向C函式堆疊幀的堆疊頂(即整個堆疊的堆疊頂),而EBP暫存器則指向C函式堆疊幀的起始位置

    (3)同時,因為主調函式尚未執行完成,所以被調函式的堆疊幀并不能覆寫主調函式的堆疊幀,只能通過push和pop指令實作呼叫

         (4)堆疊的生長方向為由高地址到低地址,資料填充則是由低地址到高地址

接下來再介紹幾個匯編指令:

  (1)call指令:執行call指令時,會將EIP的值通過push壓入堆疊中(因為EIP保存的是CPU即將執行的下一條指令的地址,所以這一步就對應前面說的保存函式回傳地址,解釋了為什么函式的回傳地址保存在主調函式中),然后將EIP的值修改為被調函式的值,則當call執行完成后,將自動呼叫目標函式(被調函式

  (2)ret指令:將call指令中壓入堆疊中的EIP的值(回傳地址)pop回到EIP中,則ret指令執行完成后,將執行主調函式的下一條指令

  (3)push指令:將ESP暫存器減去八,將ESP暫存器向高地址移動,從而開辟新的空間,然后把運算元復制到ESP所指的位置上

          在AT&T格式下:

         sub   $8    %esp

         mov   源運算元   esp

  (4)pop指令:將ESP暫存器的所存的值傳到指定位置,然后將ESP暫存器加上八

          在AT&T格式下:

          mov   %esp    目標運算元

          add    $8   %esp

  (5)leave指令:跟在ret指令后面,作用是交換esp和ebp的值

 

以下面一段程式為例:

 

#include <stdio.h>

int sum(int a, int b)
{
    int s = a + b;

    return s;
}

int main(int argc, char *argv[])
{
    int n = sum(1, 2);
    return 0;
}

 

通過gdb除錯后:

  0x0000000000400540 <+0>:push  %rbp
  0x0000000000400541 <+1>:mov   %rsp,%rbp
  0x0000000000400544 <+4>:sub   $0x20,%rsp
  0x0000000000400548 <+8>:mov   %edi,-0x14(%rbp)
  0x000000000040054b <+11>:mov   %rsi,-0x20(%rbp)
  0x000000000040054f <+15>:mov   $0x2,%esi
  0x0000000000400554 <+20>:mov   $0x1,%edi
  0x0000000000400559 <+25>:callq 0x400526 <sum>
  0x000000000040055e <+30>:mov   %eax,-0x4(%rbp)
  0x0000000000400561 <+33>:mov   -0x4(%rbp),%eax
  0x0000000000400564 <+36>:mov   %eax,%esi
  0x0000000000400566 <+38>:mov   $0x400604,%edi
  0x0000000000400575 <+53>:mov   $0x0,%eax
  0x000000000040057a<+58>:leaveq  0x000000000040057b <+59>:retq  

現在開始執行第一條指令:

0x0000000000400540 <+0>:push %rbp 
push %rbp:push指令將rsp暫存器減8開辟新的空間后,將rbp的值壓入堆疊中,此時rbp的值為呼叫main函式的函式的幀基地址,push rbp的原因是main函式需要rbp暫存器存盤自己的幀基地址,

但是又不能覆寫呼叫main函式的函式的幀基地址,因此通過push指令開辟八個位元組的空間來存盤呼叫main函式的函式的幀基地址,所以目前為止,main函式的堆疊幀中只有呼叫main函式的函式的幀基地址
同時在這條指令之前,代碼還沒有到main函式,從這條指令開始進入main函式

0x0000000000400541 <+1>:mov %rsp,%rbp 
將rsp暫存器的值賦值給rbp,使rbp和rsp指向同一個位置,即main函式堆疊幀的起始位置

0x0000000000400544 <+4>:sub $0x20,%rsp
將rsp暫存器減去32位元組,使其指向更低位置,這是為了給main函式中區域變數和臨時變數預留空間,這里注意的是,當程式開始運行時,作業系統會自動為程式分配32位元組空間,但具體使用多少由rsp暫存器決定
另外,當該指令執行完后,main函式的空間就全部分配完成,分別是存盤主調函式的8位元組和預留的32位元組

0x0000000000400548 <+8> :mov %rdi,-0x14(%rbp) #保存main函式的第1個引數
0x000000000040054b <+11>:mov %rsi,-0x20(%rbp) #保存main函式的第2個引數
0x000000000040054f <+15>:mov $0x2,%rsi #sum函式的第2個引數放入esi暫存器
0x0000000000400554 <+20>:mov $0x1,%rdi #sum函式的第1個引數放入edi暫存器
前兩條指令的目的是保存rdi和rsi的值,因為在呼叫main函式時,rdi和rsi分別保存了argc和argv兩個引數,而接下來要呼叫sum函式,則為了防止rdi和rsi中的數值被覆寫,就提前將他們存入堆疊幀中
通過rbp加偏移量的方式
后兩條指令的目的是傳遞sum函式的實參,將rsi和rdi分別賦值為2和1,同時這里有一條規定,就是函式引數保存默認暫存器順序為rdi、rsi、rdx,,,

0x0000000000400559 <+25>:callq 0x400526 <sum>  
使用call指令,如上文提到一般,call指令先將rip的值壓入堆疊中保存起來,也就是0x40055e 這個地址,這里會將rsp的值減8來開辟新的空間,然后將rip的值修改為目標函式的值,
也就是call指令的運算元0x400526,執行完成后
跳轉到sum函式

0x0000000000400526 <+0>:push  %rbp  # 保存main函式的rbp的值入堆疊             
0x0000000000400527 <+1>:mov   %rsp,%rbp # 修改當前rbp的值為當前的堆疊頂
0x000000000040052a <+4>:mov   %edi,-0x14(%rbp) # 把第1個引數放入臨時變數
0x000000000040052d <+7>:mov   %esi,-0x18(%rbp) # 把第2個引數放入臨時變數
0x0000000000400530 <+10>:mov  -0x14(%rbp),%edx # 將第1個臨時變數放入到 edx 當中
0x0000000000400533 <+13>:mov  -0x18(%rbp),%eax # 將第2個臨時變數放入到 eax 當中
0x0000000000400536 <+16>:add  %edx, %eax # 進行加法計算, 結果保存在 eax 當中
0x0000000000400538 <+18>:mov  %eax,-0x4(%rbp) # eax 的值保存到臨時變數中
0x000000000040053b <+21>:mov  -0x4(%rbp),%eax # 將臨時變數的值放入到 eax 暫存器當中
0x000000000040053e <+24>:pop  %rbp # 出堆疊, 恢復main函式的 rbp 的值
0x000000000040053f <+25>:retq  # 函式回傳

這里要注意一點就是之所以sum函式沒有修改rsp的值來預留空間是因為sum是最后一個被呼叫的函式,他沒有使用call指令,也就是說沒有將rip的值壓入堆疊中,
不需要修改rsp的值,也就是它預留的空間為堆疊中的所有剩余空間

然后繼續執行 retq 指令, 該指令把 rsp 指向的堆疊單元當中的 0x40055e 取出給 rip 暫存器, 同時 rsp 加8, 這樣,
rip 暫存器 中的值就變成了 main 函式中呼叫 sum 的 call 指令的下一條指令, 于是回傳到 main 函式中繼續執行.

繼續執行 main 函式中的:

mov %eax,-0x4(%rbp)  # sum函式的回傳值賦給變數n

該指令是把 rax 暫存器當中的值(sum函式回傳值), 放入到 rbp-4 所指的記憶體, 也就是變數 n 所在的位置,繼續執行程式結束



 

 

   

    

         

           

          

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/551568.html

標籤:其他

上一篇:【經濟機器是如何運行的】30分鐘看懂經濟的本質(無數大佬推薦)建議收藏!

下一篇:返回列表

標籤雲
其他(158377) Python(38110) JavaScript(25398) Java(18011) C(15221) 區塊鏈(8261) C#(7972) AI(7469) 爪哇(7425) MySQL(7156) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5870) 数组(5741) R(5409) Linux(5334) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4565) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1964) Web開發(1951) HtmlCss(1930) python-3.x(1918) 弹簧靴(1913) C++(1912) xml(1889) PostgreSQL(1874) .NETCore(1857) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 函式呼叫堆疊的一些簡單認識

    程式的執行可以理解為連續的函式呼叫,每一個用戶態(用戶態指的是CPU指令集權限ring 0,用戶只能訪問常用CPU指令集,在應用程式中運行)行程都對應一個呼叫堆疊結構,當一個函式執行完畢后,會自動回到原先呼叫函式的位置(call指令)的下一步命令并執行,堆疊結構的作用是保存函式回傳地址、傳遞函式引數、 ......

    uj5u.com 2023-05-04 08:01:36 more
  • 【經濟機器是如何運行的】30分鐘看懂經濟的本質(無數大佬推薦)建議

    視頻來源: https://www.bilibili.com/video/BV1qG4y157qp/?share_source=copy_web&vd_source=185624f32058093bb3ad55ee7f1c12b1 總結: 1、不要讓債務的增長速度超過收入。 當債務增長速度超過的你的 ......

    uj5u.com 2023-05-04 08:01:32 more
  • kubernetes入門

    一.導言 隨著容器技術的發展,軟體界對容器管理的需求越來越迫切,于是出現了一些kubernetes(即k8s),docker swarm 等容器管理軟體。同時k8s等服務編排軟體也讓微服務變得可行,快速擴容縮容,自動處理網路配置等特性也讓k8s如火如荼。 k8s能做什么? 服務發現和負載均衡,使用d ......

    uj5u.com 2023-05-04 08:01:15 more
  • dqwwn1-服務器弱點

    主機發現 sudo nmap -sn 192.168.28.0/24 TCP埠掃描:sudo nmap -sT --min-rate 1000 -p- 192.168.28.34 -oA nmapscan/ports TCP埠版本掃描sudo nmap -sT -sV -sC -O -p22,8 ......

    uj5u.com 2023-05-04 07:55:49 more
  • 再一次,實作聽歌自由

    20年前,中國網民聽歌是自由的,準確點說是聽盜版歌的自由。2002年11月,百度上線MP3搜索功能,幾乎能搜索和下載到所有的歌曲。按相關的著作權法規,百度未經授權使用他人資源牟利是違法的。當時互聯網產業違法采集資料、傳播盜版是家常便飯,著作權管理形同虛設,百度順勢而為分了一塊大蛋糕。盜版音樂砸了音樂人的... ......

    uj5u.com 2023-05-04 07:39:47 more
  • 【經濟機器是如何運行的】30分鐘看懂經濟的本質(無數大佬推薦)建議

    視頻來源: https://www.bilibili.com/video/BV1qG4y157qp/?share_source=copy_web&vd_source=185624f32058093bb3ad55ee7f1c12b1 總結: 1、不要讓債務的增長速度超過收入。 當債務增長速度超過的你的 ......

    uj5u.com 2023-05-04 07:39:14 more
  • 函式呼叫堆疊的一些簡單認識

    程式的執行可以理解為連續的函式呼叫,每一個用戶態(用戶態指的是CPU指令集權限ring 0,用戶只能訪問常用CPU指令集,在應用程式中運行)行程都對應一個呼叫堆疊結構,當一個函式執行完畢后,會自動回到原先呼叫函式的位置(call指令)的下一步命令并執行,堆疊結構的作用是保存函式回傳地址、傳遞函式引數、 ......

    uj5u.com 2023-05-04 07:38:35 more
  • dqwwn1-服務器弱點

    主機發現 sudo nmap -sn 192.168.28.0/24 TCP埠掃描:sudo nmap -sT --min-rate 1000 -p- 192.168.28.34 -oA nmapscan/ports TCP埠版本掃描sudo nmap -sT -sV -sC -O -p22,8 ......

    uj5u.com 2023-05-04 07:38:21 more
  • chatGPT問答之 Webpack 5 多入口打包如何指定打包檔案名規定的檔

    前言 chatGPT越來越令人驚奇,有一些答案在百度上搜半天卻找不到你想要的,但與chatGPT的聊天中就可以非常快的得到你想要的結果,不得不說人工智能很好用下面就是我與chatGPT的聊天內容 chatGPT問答之 Webpack 5 多入口打包如何指定打包檔案名規定的檔案名 問1: Webpac ......

    uj5u.com 2023-05-03 07:33:24 more
  • Vulnhub之Gain Power靶機詳細測驗程序

    Gain Power 識別目標主機IP地址 (kali?kali)-[~/Vulnhub/Gainpower] └─$ sudo netdiscover -i eth1 -r 192.168.56.0/24 Currently scanning: 192.168.56.0/24 | Screen V ......

    uj5u.com 2023-05-03 07:33:18 more