最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談C語(yǔ)言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問題

 更新時(shí)間:2016年09月25日 20:08:06   投稿:jingxian  
下面小編就為大家?guī)硪黄獪\談C語(yǔ)言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

參數(shù)入棧的順序

以前在面試中被人問到這樣的問題,函數(shù)調(diào)用的時(shí)候,參數(shù)入棧的順序是從左向右,還是從右向左。參數(shù)的入棧順序主要看調(diào)用方式,一般來說,__cdecl 和__stdcall 都是參數(shù)從右到左入棧。

看下面的代碼:

#include <stdio.h>

int test(int a, int b)
{
  printf("address of a %x.\n", &a);
  printf("address of b %x.\n", &b);
  return 0;
}

int main()
{
  test(1, 2);
  return 0;
}

在64位Ubuntu的系統(tǒng)下的運(yùn)行結(jié)果是:

address of a 1ec62c. 
address of b 1ec628.

32位Ubuntu的結(jié)果是:

address of a bfd03290. 
address of b bfd03294.

可以看出,首先,不同的體系結(jié)構(gòu),棧增長(zhǎng)的方向也不同,有的是從低地址向高地址方向增長(zhǎng),有的是從高地址向低地址方向增長(zhǎng)。

可以用以下的代碼來判斷棧的增長(zhǎng)方向:

typedef enum {
  LOW_TO_HIGH,
  HIGH_TO_LOW,
  LEFT_TO_RIGHT,
  RIGHT_TO_LEFT,
}stack_direc_t;

int stack_grow_direc()
{
  static char *p = NULL;
  char c;

  if (p == NULL) {
    p = &c;
    stack_grow_direc();
  }
  else {
    printf("First in stack address is %x.\n", p);
    printf("Second in stack address is %x.\n", &c);
    if (&c > p) {
      printf("Stack grows from low address to high address!\n");
      return LOW_TO_HIGH;
    }
    else {
      printf("Stack grows from high address to low address!\n");
      return HIGH_TO_LOW;
    }
  }
}

函數(shù)調(diào)用時(shí)棧里都有什么

以參數(shù)從左到右入棧為例:

push arg0 -- High Address
push arg1
...
push argn
push eip
push ebp -- Low address

32位系統(tǒng)和64位系統(tǒng)函數(shù)調(diào)用時(shí),參數(shù)入棧方式有不同么?

這個(gè)問題在不久之前被人問題,當(dāng)時(shí)傻了,我一直以來只關(guān)注過32位系統(tǒng)的參數(shù)入棧方式,一直以為64位系統(tǒng)也是一樣,沒有什么不同,現(xiàn)在歸納起來有兩點(diǎn):

64位系統(tǒng)先把傳入?yún)?shù)放在寄存器里面,在被調(diào)函數(shù)的具體實(shí)現(xiàn)中把寄存器的值入棧,然后再去棧中取參數(shù)

64位系統(tǒng)棧中參數(shù)存放的順序是從左至右的(因?yàn)橄冉?jīng)歷了寄存器傳值)

看下面的反匯編:


C代碼同上面一樣
Ubuntu 32位反匯編:
int main()
{
 804846d:  55           push  %ebp
 804846e:  89 e5          mov  %esp,%ebp
 8048470:  83 e4 f0        and  $0xfffffff0,%esp
 8048473:  83 ec 10        sub  $0x10,%esp
  test(1, 2);
 8048476:  c7 44 24 04 02 00 00  movl  $0x2,0x4(%esp)
 804847d:  00 
 804847e:  c7 04 24 01 00 00 00  movl  $0x1,(%esp)
 8048485:  e8 8a ff ff ff     call  8048414 <test>
  return 0;
 804848a:  b8 00 00 00 00     mov  $0x0,%eax
}
int test(int a, int b)
{
 8048414:  55           push  %ebp
 8048415:  89 e5          mov  %esp,%ebp
 8048417:  83 ec 18        sub  $0x18,%esp
  printf("address of a %x.\n", &a);
 804841a:  b8 60 85 04 08     mov  $0x8048560,%eax
 804841f:  8d 55 08        lea  0x8(%ebp),%edx
 8048422:  89 54 24 04       mov  %edx,0x4(%esp)
 8048426:  89 04 24        mov  %eax,(%esp)
 8048429:  e8 12 ff ff ff     call  8048340 <printf@plt>

  return 0;
 8048466:  b8 00 00 00 00     mov  $0x0,%eax
}
Ubuntu 64位反匯編:
int main()
{
 40056e:  55           push  %rbp
 40056f:  48 89 e5        mov  %rsp,%rbp
  test(1, 2);
 400572:  be 02 00 00 00     mov  $0x2,%esi
 400577:  bf 01 00 00 00     mov  $0x1,%edi
 40057c:  e8 ac ff ff ff     callq 40052d <test>
  return 0;
 400581:  b8 00 00 00 00     mov  $0x0,%eax
}
int test(int a, int b)
{
 40052d:  55           push  %rbp
 40052e:  48 89 e5        mov  %rsp,%rbp
 400531:  48 83 ec 10       sub  $0x10,%rsp
 400535:  89 7d fc        mov  %edi,-0x4(%rbp)
 400538:  89 75 f8        mov  %esi,-0x8(%rbp)
  printf("address of a %x.\n", &a);
 40053b:  48 8d 45 fc       lea  -0x4(%rbp),%rax
 40053f:  48 89 c6        mov  %rax,%rsi
 400542:  bf 14 06 40 00     mov  $0x400614,%edi
 400547:  b8 00 00 00 00     mov  $0x0,%eax
 40054c:  e8 bf fe ff ff     callq 400410 <printf@plt>

  return 0;
 400567:  b8 00 00 00 00     mov  $0x0,%eax
}

看32位的ubuntu操作系統(tǒng), 8048476: 的確是把參數(shù)直接入棧,2先入棧,1后入棧。

 8048476:  c7 44 24 04 02 00 00  movl  $0x2,0x4(%esp)
 804847d:  00 
 804847e:  c7 04 24 01 00 00 00  movl  $0x1,(%esp)
 8048485:  e8 8a ff ff ff     call  8048414 <test>

再來看64位的ubuntu操作系統(tǒng),2 和1根本就沒有放入到棧中,而是放到了寄存器esi和edi中。

 40056f:  48 89 e5        mov  %rsp,%rbp
 test(1, 2);
 400572:  be 02 00 00 00     mov  $0x2,%esi
 400577:  bf 01 00 00 00     mov  $0x1,%edi
 40057c:  e8 ac ff ff ff     callq 40052d <test>

再來看64位系統(tǒng)test的實(shí)現(xiàn),先把edi入棧,再把esi入棧,這就是為什么函數(shù)看起來像是從左到右入棧的原因了。

40052d:  55           push  %rbp
40052e:  48 89 e5        mov  %rsp,%rbp
400531:  48 83 ec 10       sub  $0x10,%rsp
400535:  89 7d fc        mov  %edi,-0x4(%rbp)
400538:  89 75 f8        mov  %esi,-0x8(%rbp)

以上就是小編為大家?guī)淼臏\談C語(yǔ)言函數(shù)調(diào)用參數(shù)壓棧的相關(guān)問題的全部?jī)?nèi)容了,希望對(duì)大家有所幫助,多多支持腳本之家~

相關(guān)文章

  • Linux下Select多路復(fù)用實(shí)現(xiàn)簡(jiǎn)易聊天室示例

    Linux下Select多路復(fù)用實(shí)現(xiàn)簡(jiǎn)易聊天室示例

    大家好,本篇文章主要講的是Linux下Select多路復(fù)用實(shí)現(xiàn)簡(jiǎn)易聊天室示例,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C++使用printf語(yǔ)句實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換的示例代碼

    C++使用printf語(yǔ)句實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換的示例代碼

    在C語(yǔ)言中,printf 函數(shù)可以直接實(shí)現(xiàn)部分進(jìn)制轉(zhuǎn)換功能,通過格式說明符(format specifier)快速輸出不同進(jìn)制的數(shù)值,下面給大家分享C++使用printf語(yǔ)句實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換的示例代碼,感興趣的朋友一起看看吧
    2025-04-04
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)順序表中的增刪改(頭插頭刪)教程示例詳解

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)順序表中的增刪改(頭插頭刪)教程示例詳解

    這篇文章主要為大家介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)順序表中增刪改關(guān)于頭插頭刪的教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • 基于matlab MFCC+GMM的安全事件聲學(xué)檢測(cè)系統(tǒng)

    基于matlab MFCC+GMM的安全事件聲學(xué)檢測(cè)系統(tǒng)

    這篇文章主要為大家介紹了基于matlab MFCC+GMM的安全事件聲學(xué)檢測(cè)系統(tǒng)實(shí)現(xiàn)及源碼示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • ros項(xiàng)目調(diào)試:vscode下配置開發(fā)ROS項(xiàng)目的詳細(xì)教程

    ros項(xiàng)目調(diào)試:vscode下配置開發(fā)ROS項(xiàng)目的詳細(xì)教程

    這篇文章主要介紹了ros項(xiàng)目調(diào)試:vscode下配置開發(fā)ROS項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • C++移動(dòng)語(yǔ)義介紹與使用講解

    C++移動(dòng)語(yǔ)義介紹與使用講解

    首先,移動(dòng)語(yǔ)義和完美轉(zhuǎn)發(fā)這兩個(gè)概念是在C++的模板編程的基礎(chǔ)上,新增的特性,主要是配合模板來使用。本篇會(huì)從C++的值類型,到移動(dòng)拷貝與移動(dòng)賦值來理解移動(dòng)語(yǔ)義與完美轉(zhuǎn)發(fā)
    2022-09-09
  • C++ static的作用解讀

    C++ static的作用解讀

    這篇文章主要介紹了C++ static的作用及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語(yǔ)言WinSock學(xué)習(xí)筆記

    C語(yǔ)言WinSock學(xué)習(xí)筆記

    本篇文章主要介紹了C語(yǔ)言WinSock學(xué)習(xí)筆記,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2007-12-12
  • C++實(shí)現(xiàn)簡(jiǎn)單通訊錄

    C++實(shí)現(xiàn)簡(jiǎn)單通訊錄

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 如何使用Qt實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)繪制的折線圖效果

    如何使用Qt實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)繪制的折線圖效果

    使用Qt的QChartView和定時(shí)器,本教程詳細(xì)介紹了如何動(dòng)態(tài)繪制折線圖,通過定時(shí)器觸發(fā)數(shù)據(jù)點(diǎn)的動(dòng)態(tài)添加和坐標(biāo)軸范圍的自動(dòng)調(diào)整,實(shí)現(xiàn)了實(shí)時(shí)更新數(shù)據(jù)的動(dòng)態(tài)折線圖應(yīng)用,程序結(jié)合QLineSeries或QSplineSeries繪制折線或樣條曲線,配合動(dòng)畫效果,展現(xiàn)數(shù)據(jù)變化
    2024-10-10

最新評(píng)論

来凤县| 西城区| 连江县| 吴旗县| 炉霍县| 阿巴嘎旗| 安仁县| 盐源县| 大兴区| 措勤县| 衡阳市| 邵东县| 虹口区| 灌云县| 东宁县| 湘阴县| 桂平市| 三门县| 年辖:市辖区| 小金县| 石首市| 铜梁县| 麻城市| 鄂州市| 永登县| 交口县| 大连市| 江门市| 从江县| 平南县| 清原| 射阳县| 英德市| 大关县| 淳化县| 航空| 比如县| 高雄市| 南溪县| 达州市| 淳化县|