欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++ 函數(shù)原理傳參示例詳解

 更新時間:2022年12月07日 15:02:29   作者:amjieker  
這篇文章主要為大家介紹了C/C++ 函數(shù)原理傳參示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

x84-64的寄存器

本文所用gccx86-64 gcc 10.1

wiki.cdot.senecacollege.ca/wiki/X86_64…

rax - register a extended

rbx - register b extended

rcx - register c extended

rdx - register d extended

rbp - register base pointer (start of stack)

rsp - register stack pointer (current location in stack, growing downwards)

rsi - register source index (source for data copies)

rdi - register destination index (destination for data copies)

其他寄存器: r8 r9 r10 r11 r12 r13 r14 r15

函數(shù)是個什么東西?

一個簡單的函數(shù)

int func(){}
int main() {
    int x = 2;
    func();
}
main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
        movl    $2, -4(%rbp)
        call    func()
        movl    $0, %eax
        leave
        ret

分配空間動作如下所示:

這里加了個函數(shù)調(diào)用是因為在有些時候,沒有函數(shù)調(diào)用,就不會使用subq $16, %rsp 這一條指令,我的猜想是既然你都是棧頂?shù)模⑶也粫儆衦bp的變化,那么棧頂以上的元素我都可以隨便用。
并且我們觀察可以得知,分配棧空間時,他是分配的16個字節(jié),也就是說,有對齊
返回時,彈出棧頂,就可以恢復(fù)到上一個棧幀的狀態(tài)了。

傳參姿勢

入棧規(guī)則

c/c++ 中規(guī)定的函數(shù)壓棧順序是從右到左,當(dāng)然,如果你是 Visual C/C++的話,它們有更多的玩法 比如:

template<typename T>
T val(T t) {
  cout << t << endl;
  return t;
}
signed main() {
  printf("%d%d%d", val(1), val(2), val(3));
  return 0;
}

結(jié)果

3
2
1
123

看看匯編

int func(int x, int y, int z) {
  return 0;
}
int main() {
  func(1, 2, 3);
}

生成的匯編

func(int, int, int):
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        movl    %edx, -12(%rbp)
        movl    $0, %eax
        popq    %rbp
        ret
main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $3, %edx
        movl    $2, %esi
        movl    $1, %edi
        call    func(int, int, int)
        movl    $0, %eax
        popq    %rbp
        ret

上文中可以看出,也證實了我們所觀察到的,首先把3傳給了edx,2傳給了esi,1傳給了edi

全都存寄存器嗎?

寄存器畢竟少,當(dāng)然,還可以存在棧上嘛

int fun() {return 0;}
int func(int x, int y, int z, int a, int b, int c, int d, int e, int f){
    fun();
    return e;
}
int main() {
    func(1, 2, 3, 4, 5, 6, 7, 8, 9);
    return 0;
}
fun():
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $0, %eax
        popq    %rbp
        ret
func(int, int, int, int, int, int, int, int, int):
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $24, %rsp
        movl    %edi, -4(%rbp)
        movl    %esi, -8(%rbp)
        movl    %edx, -12(%rbp)
        movl    %ecx, -16(%rbp)
        movl    %r8d, -20(%rbp)
        movl    %r9d, -24(%rbp)
        call    fun()
        movl    24(%rbp), %eax
        leave
        ret
main:
        pushq   %rbp
        movq    %rsp, %rbp
        pushq   $9  // 24+%rbp
        pushq   $8  // 16+%rbp
        pushq   $7  // 8 +%rbp
        movl    $6, %r9d
        movl    $5, %r8d
        movl    $4, %ecx
        movl    $3, %edx
        movl    $2, %esi
        movl    $1, %edi
        call    func(int, int, int, int, int, int, int, int, int)
        addq    $24, %rsp
        movl    $0, %eax
        leave
        ret

主函數(shù)中的這三條語句

pushq   $9
pushq   $8
pushq   $7

說明了,當(dāng)函數(shù)入棧放寄存器放不下時,會放在棧上,放在棧頂之上,等函數(shù)調(diào)用執(zhí)行完成后,rbp取出回到當(dāng)前位置之后,再去addq $24, %rsp 把棧彈出這些元素。

并且func函數(shù)中的movl 24(%rbp), %eax也證明了,傳的參數(shù)是在棧頂?shù)纳厦妫ㄗ陨舷蛳略鲩L) 24 + %rbp 剛好是 $9, 也就是局部變量f的位置

傳對象呢?

在這里,暫且不談內(nèi)存布局,把一個對象看成一塊內(nèi)存對于的位置
這里用一個結(jié)構(gòu)體做示例

struct E {int x, y, z;};
E func(E e){
    e.x = 2;
    return e;
}
int main() {
    E e = {.x = 1, .y = 2, .z = 3};
    e = func(e);
    return 0;
}
func(E):
        pushq   %rbp
        movq    %rsp, %rbp
        // 將rdi 和 esi 取出來 放到 rdx 和 eax 中
        movq    %rdi, %rdx
        movl    %esi, %eax
        // 存放到開辟好的空間中 {x = rbp - 32, y = rbp - 28, z = rbp - 24}
        movq    %rdx, -32(%rbp)
        movl    %eax, -24(%rbp)
        // 更改 x
        movl    $2, -32(%rbp)
        // 將值移動到寄存器上,從返回寄存器上移動到局部返回出去的變量
        movq    -32(%rbp), %rax
        movq    %rax, -12(%rbp)
        movl    -24(%rbp), %eax
        movl    %eax, -4(%rbp)
        // 將返回值值移動到寄存器上 rax rdx 上
        movq    -12(%rbp), %rax
        movl    -4(%rbp), %ecx
        movq    %rcx, %rdx
        popq    %rbp
        ret
main:
        // 壓棧保存現(xiàn)場 沒什么好說的
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
        // 內(nèi)存布局
        rbp
        | z  rbp - 4  
        | y  rbp - 8
        | x  rbp - 12
        movl    $1, -12(%rbp)
        movl    $2, -8(%rbp)
        movl    $3, -4(%rbp)
        // 移動 x 和 y 到 rdx 寄存器中
        movq    -12(%rbp), %rdx
        // 移動 z 到 eax中
        movl    -4(%rbp), %eax
        // 再將 rdx 和 eax 分別移動到rdi 和 esi中
        movq    %rdx, %rdi
        movl    %eax, %esi
        call    func(E)
        // 從rax 中取出x y
        movq    %rax, -12(%rbp)
        // 從rdx中取出z
        movl    -4(%rbp), %eax
        andl    $0, %eax
        orl     %edx, %eax //
        movl    %eax, -4(%rbp)
        movl    $0, %eax
        leave
        ret

以上就是C/C++ 函數(shù)原理傳參示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C/C++ 函數(shù)原理傳參的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++實現(xiàn)點云添加高斯噪聲功能

    C++實現(xiàn)點云添加高斯噪聲功能

    所謂高斯噪聲是指它的概率密度函數(shù)服從高斯分布(即正態(tài)分布)的一類噪聲,這篇文章主要給大家介紹了關(guān)于C++實現(xiàn)點云添加高斯噪聲功能的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • C++基礎(chǔ)學(xué)習(xí)之函數(shù)重載的簡單介紹

    C++基礎(chǔ)學(xué)習(xí)之函數(shù)重載的簡單介紹

    函數(shù)重載是一種特殊情況,C++允許在同一作用域中聲明幾個類似的同名函數(shù),這些同名函數(shù)的形參列表(參數(shù)個數(shù),類型,順序)必須不同,常用來處理實現(xiàn)功能類似數(shù)據(jù)類型不同的問題。這篇文章主要給大家介紹了關(guān)于C++基礎(chǔ)學(xué)習(xí)之函數(shù)重載的相關(guān)資料,需要的朋友可以參考下
    2019-01-01
  • c語言常見圖片格式判斷實例

    c語言常見圖片格式判斷實例

    這篇文章介紹了c語言常見圖片格式判斷實例,有需要的朋友可以參考一下
    2013-09-09
  • C語言實現(xiàn)電子郵件地址驗證程序

    C語言實現(xiàn)電子郵件地址驗證程序

    這篇文章主要介紹了C語言實現(xiàn)電子郵件地址驗證程序,利用的是POSIX正則表達(dá)式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-11-11
  • C++深入探究用NULL來初始化空指針是否合適

    C++深入探究用NULL來初始化空指針是否合適

    在C++11新特性中,我們用nullptr來表示指針空值,這是為什么呢?好好地NULL為什么不繼續(xù)使用呢?說明在創(chuàng)造C++的大佬們一定發(fā)現(xiàn)了什么Bug,本篇我們就一起來討論一下吧
    2022-05-05
  • C++實現(xiàn)LeetCode(132.拆分回文串之二)

    C++實現(xiàn)LeetCode(132.拆分回文串之二)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(132.拆分回文串之二),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 如何實現(xiàn)一定概率選中某一個字母

    如何實現(xiàn)一定概率選中某一個字母

    本篇文章是對如何實現(xiàn)一定概率選中某一個字母的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++Lambda表達(dá)式詳解

    C++Lambda表達(dá)式詳解

    這篇文章主要介紹了C++中的Lambda表達(dá)式詳解,本文講解了基本語法、Lambda的使用等內(nèi)容,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-10-10
  • 如何使用C++獲取指定的重載函數(shù)地址

    如何使用C++獲取指定的重載函數(shù)地址

    重載函數(shù)是完全不同的幾個函數(shù),有不同的函數(shù)地址,下面這篇文章主要給大家介紹了關(guān)于如何使用C++獲取指定的重載函數(shù)地址的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • C語言題目:有多少張桌子--并查集

    C語言題目:有多少張桌子--并查集

    并查集是一種用于管理分組的數(shù)據(jù)結(jié)構(gòu)。它具備兩個操作:(1)查詢元素a和元素b是否為同一組 (2) 將元素a和b合并為同一組,需要的朋友可以參考下
    2021-09-09

最新評論