九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
c++函數(shù)調(diào)用過(guò)程分析(匯編語(yǔ)言編碼是ATT模式 可以手動(dòng)修改為intel風(fēng)格依個(gè)人喜好我個(gè)人更偏向intel風(fēng)格)

https://www.toutiao.com/article/7287409808045818428/?log_from=cca2e23dd92df_1697203661621

 

  (用objdump反匯編時(shí)可以把C代碼和匯編代碼穿插起來(lái)顯示這樣C代碼和匯編代碼的對(duì)應(yīng)關(guān)系看得更清楚)

(匯編語(yǔ)言編碼是ATT模式 可以手動(dòng)修改為intel風(fēng)格依個(gè)人喜好我個(gè)人更偏向intel風(fēng)格)

調(diào)用過(guò)程

  1. 調(diào)用者把函數(shù)的參數(shù)按照調(diào)用約定壓?;虼鎯?chǔ)到寄存器中。

  2. 調(diào)用要使用的函數(shù),先把調(diào)用者的地址入棧,方便回來(lái)

  3. 跳轉(zhuǎn)到函數(shù)

  4. 把函數(shù)使用到的一些寄存器壓棧,避免修改寄存器的值

  5. 執(zhí)行函數(shù)

  6. 處理函數(shù)返回值

  7. 對(duì)于第4步中的壓棧的那些寄存器,恢復(fù)他們?cè)瓉?lái)的值

  8. 清空第一步中的壓棧參數(shù)和處理返回值

  9. 返回到調(diào)用者調(diào)用時(shí)的地址(步驟1已經(jīng)記錄)繼續(xù)往下執(zhí)行

實(shí)驗(yàn)分析

系統(tǒng):centos 7,64位。64位基本使用寄存器存儲(chǔ)函數(shù)參數(shù),寄存器不夠才入棧。

32位使用棧幀來(lái)作為傳遞的參數(shù)的保存位置,而64位使用寄存器,分別用rdi, rsi, rdx, rcx, r8, r9作為第1-6個(gè)參數(shù),rax作為返回值。

用gdb調(diào)試,測(cè)試代碼如下:test.c

#include <stdio.h>
int add(int a, int b, int c)
{
   return (a + b + c);
}

int main()
{
    int sum = 0;
    int a = 1;
    int b = 2;
    int c = 3;
    sum = add(a, b ,c);
    sum = sum + 1;
    return 0;
}

編譯

編譯時(shí)加上-g選項(xiàng),那么用objdump反匯編時(shí)可以把C代碼和匯編代碼穿插起來(lái)顯示,這樣C代碼和匯編代碼的對(duì)應(yīng)關(guān)系看得更清楚。

gcc test.c -g
objdump -dS a.out

匯編后的代碼如下

00000000004004e9 <main>:
int main()
{
    4004e9:         push %rbp                 ; rbp入棧,即將調(diào)用main()的函數(shù)的棧底地址放入棧中
    4004ea:         mov %rsp, %rbp            ; 將rsp的值給rbp,此時(shí)rbp指向新的棧底
    4004ed:         sub $0x10, %rsp           ; rsp - 0x10,為main函數(shù)開辟空間
        int sum = 0;
    4004f1: c7 45 fc 00
}

gdb跟蹤,在main函數(shù)設(shè)置斷點(diǎn)

看當(dāng)前的匯編

默認(rèn)的匯編語(yǔ)言編碼是ATT模式。如果看不順的話,可以手動(dòng)修改為intel風(fēng)格,依個(gè)人喜好,我個(gè)人更偏向intel風(fēng)格

set disassembly-flavor intel

剛開始用到了rbp,rsp。那先重點(diǎn)關(guān)注rbp,rsp,cs,rip這四個(gè)寄存器

通過(guò)如下命令查看

info registers rbp rsp cs rip
或者
print $rbp

通過(guò)畫圖來(lái)分析棧里面當(dāng)前的數(shù)據(jù)

1,設(shè)置棧底和棧頂

00000000004004e9 <main>:
int main()
{
    4004e9:         push %rbp                 ; rbp入棧,即將調(diào)用main()的函數(shù)的棧底地址放入棧中
    4004ea:         mov %rsp, %rbp            ; 將rsp的值給rbp,此時(shí)rbp指向新的棧底
    4004ed:         sub $0x10, %rsp           ; rsp - 0x10,為main函數(shù)開辟空間

過(guò)程如圖

來(lái)看下舊rbp里面的值,通過(guò)x /nfu addr來(lái)查看內(nèi)存里面的值,如下



發(fā)現(xiàn)舊rbp為0x0,這里不做擴(kuò)展,繼續(xù)

2,局部變量入棧

匯編語(yǔ)句的單步調(diào)試(si 4),向前4步

代碼解釋

00000000004004e9 <main>:
int main()
{
    ...
    4004f1:         mov DWORD PTR [rbp-0x4],  0x0                 ; sum入棧
    4004f8:         mov DWORD PTR [rbp-0x8],  0x1                 ; a入棧
    4004ff:         mov DWORD PTR [rbp-0xc],  0x2                 ; b入棧
    400506:         mov DWORD PTR [rbp-0x10], 0x3                 ; c入棧
    ...

此時(shí)如下圖

3,被調(diào)函數(shù)的參數(shù)儲(chǔ)存在寄存器中

00000000004004e9 <main>:
int main()
{
    ...
    mov edx, DWORD PTR [rbp-0x10]
    mov ecx, DWORD PTR [rbp-0xc]
    mov eax, DWORD PTR [rbp-0x8]
    ...

向前3步(si 3)

寄存器

edx

c(3)

ecx

b(2)

eax

a(1)

00000000004004e9 <main>:
int main()
{
    ...
    mov esi, ecx
    mov edi, eax
    ...

寄存器

esi

ecx(b:2)

edi

eax(a:1)

4,跳轉(zhuǎn)函數(shù)

此時(shí)rip寄存器的值為:

執(zhí)行call語(yǔ)句后

call語(yǔ)句分解為:

push rip;

jump ip;

看各個(gè)寄存器的值

看rsp的值為:0x7fff,ffff,e4b8,看入棧的返回地址的值; rip 為0x4004cd

即0x40051f正好對(duì)應(yīng)于call下面的語(yǔ)句

5,執(zhí)行函數(shù),將main函數(shù)的棧底壓棧,并將rsp的值給rbp,此時(shí)rbp指向新的棧底

00000000004004cd <add>:
int add(int a, int b, int c)
{
    4004cd:    push rbp
    4004ce:    mov  rbp, rsp
    ...
}

rbp和rsp相等

6,將局部變量壓棧

00000000004004cd <add>:
int add(int a, int b, int c)
{
    ...
    4004d1:    mov DWORD PTR [rbp-0x4],  edi
    4004d4:    mov DWORD PTR [rbp-0x8],  esi
    4004d7:    mov DWORD PTR [rbp-0xc],  edx
    ...
}

7, 開始計(jì)算

00000000004004cd <add>:
int add(int a, int b, int c)
{
    ...
    4004da:    mov eax, DWORD PTR [rbp-0x8];        eax = b = 1
    4004dd:    mov edx, DWORD PTR [rbp-0x4];        edx = a = 2
    4004e0:    add edx, eax;                        								edx = eax + edx = 3;
    4004e2:    mov eax, DWORD PTR [rbp-0xc];        eax = c = 3
    4004e5:    add eax, edx;                        								eax = eax + edx = 6, 即返回值保存在寄存器eax中
    ...
}

8,恢復(fù)rbp

各個(gè)寄存器的值

00000000004004cd <add>:
int add(int a, int b, int c)
{
    ...
    4004e7:    pop rbp

9,回到main函數(shù)

00000000004004cd <add>:
int add(int a, int b, int c)
{
    ...
    4004e8:    ret

ret的作用是: pop rip

10,返回值賦值

00000000004004e9 <main>:
int main()
{
    ...
        sum = add(a, b, c)
    ...
    mov DWORD PTR [rbp-0x4], eax   ; 將eax的值賦值給sum
        sum = sum + 1;
    add DWORD PTR [rbp-0x4], 0x1   ; sum += 1
        return 0;
    mov eax, 0x0                   ; 將返回值0通過(guò)eax傳遞
    ...

11,執(zhí)行l(wèi)eave

執(zhí)行前

執(zhí)行后

rbp = 0

rsp = 0x7fff,ffff,e4d8

12,執(zhí)行ret,回到_libc_start_main函數(shù)里


(匯編語(yǔ)言編碼是ATT模式 可以手動(dòng)修改為intel風(fēng)格依個(gè)人喜好我個(gè)人更偏向intel風(fēng)格)

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
讀懂操作系統(tǒng)(x64)之堆棧幀(過(guò)程調(diào)用)
通過(guò)匯編語(yǔ)言來(lái)深入理解程序
函數(shù)堆棧平衡
分享一個(gè)有意思的gdb插件
GCC內(nèi)建函數(shù) __builtin_return_address實(shí)現(xiàn)
【代碼真相】函數(shù)調(diào)用 堆棧 轉(zhuǎn)載 - liangxiufei - 博客園
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服