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

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

 更新時(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ù)是個(gè)什么東西?

一個(gè)簡(jiǎn)單的函數(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

分配空間動(dòng)作如下所示:

這里加了個(gè)函數(shù)調(diào)用是因?yàn)樵谟行r(shí)候,沒(méi)有函數(shù)調(diào)用,就不會(huì)使用subq $16, %rsp 這一條指令,我的猜想是既然你都是棧頂?shù)?,并且不?huì)再有rbp的變化,那么棧頂以上的元素我都可以隨便用。
并且我們觀察可以得知,分配??臻g時(shí),他是分配的16個(gè)字節(jié),也就是說(shuō),有對(duì)齊
返回時(shí),彈出棧頂,就可以恢復(fù)到上一個(gè)棧幀的狀態(tài)了。

傳參姿勢(shì)

入棧規(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

上文中可以看出,也證實(shí)了我們所觀察到的,首先把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ù)中的這三條語(yǔ)句

pushq   $9
pushq   $8
pushq   $7

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

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

傳對(duì)象呢?

在這里,暫且不談內(nèi)存布局,把一個(gè)對(duì)象看成一塊內(nèi)存對(duì)于的位置
這里用一個(gè)結(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 取出來(lái) 放到 rdx 和 eax 中
        movq    %rdi, %rdx
        movl    %esi, %eax
        // 存放到開(kāi)辟好的空間中 {x = rbp - 32, y = rbp - 28, z = rbp - 24}
        movq    %rdx, -32(%rbp)
        movl    %eax, -24(%rbp)
        // 更改 x
        movl    $2, -32(%rbp)
        // 將值移動(dòng)到寄存器上,從返回寄存器上移動(dòng)到局部返回出去的變量
        movq    -32(%rbp), %rax
        movq    %rax, -12(%rbp)
        movl    -24(%rbp), %eax
        movl    %eax, -4(%rbp)
        // 將返回值值移動(dòng)到寄存器上 rax rdx 上
        movq    -12(%rbp), %rax
        movl    -4(%rbp), %ecx
        movq    %rcx, %rdx
        popq    %rbp
        ret
main:
        // 壓棧保存現(xiàn)場(chǎng) 沒(méi)什么好說(shuō)的
        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)
        // 移動(dòng) x 和 y 到 rdx 寄存器中
        movq    -12(%rbp), %rdx
        // 移動(dòng) z 到 eax中
        movl    -4(%rbp), %eax
        // 再將 rdx 和 eax 分別移動(dòng)到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ù)原理傳參的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

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

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

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

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

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

    c語(yǔ)言常見(jiàn)圖片格式判斷實(shí)例

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

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

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

    C++深入探究用NULL來(lái)初始化空指針是否合適

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

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

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

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

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

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

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

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

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

    C語(yǔ)言題目:有多少?gòu)堊雷?-并查集

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

最新評(píng)論