奶头挺立呻吟高潮av全片,成人试看120秒体验区,性欧美极品v,A片高潮抽搐揉捏奶头视频

C語言

淺談C語言函數調用參數壓棧的相關問題

時間:2024-11-03 21:15:07 C語言 我要投稿
  • 相關推薦

關于淺談C語言函數調用參數壓棧的相關問題

  參數入棧的順序

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

  看下面的代碼:

  #includeint 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的系統下的運行結果是:

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

  32位Ubuntu的結果是:

  address of a bfd03290. address of b bfd03294.

  可以看出,首先,不同的體系結構,棧增長的方向也不同,有的是從低地址向高地址方向增長,有的是從高地址向低地址方向增長。

  可以用以下的代碼來判斷棧的增長方向:

  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; } }}

  函數調用時棧里都有什么

  以參數從左到右入棧為例:

  push arg0 -- High Addresspush arg1...push argnpush eippush ebp -- Low address

  32位系統和64位系統函數調用時,參數入棧方式有不同么?

  這個問題在不久之前被人問題,當時傻了,我一直以來只關注過32位系統的參數入棧方式,一直以為64位系統也是一樣,沒有什么不同,現在歸納起來有兩點:

  64位系統先把傳入參數放在寄存器里面,在被調函數的具體實現中把寄存器的值入棧,然后再去棧中取參數

  64位系統棧中參數存放的順序是從左至右的(因為先經歷了寄存器傳值)

  看下面的反匯編:

  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 8048414return 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 8048340return 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 40052dreturn 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 400410return 0; 400567: b8 00 00 00 00 mov $0x0,%eax}

  看32位的ubuntu操作系統, 8048476: 的確是把參數直接入棧,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

  再來看64位的ubuntu操作系統,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

  再來看64位系統test的實現,先把edi入棧,再把esi入棧,這就是為什么函數看起來像是從左到右入棧的原因了。

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

【淺談C語言函數調用參數壓棧的相關問題】相關文章:

C語言函數參數傳遞問題10-17

C語言函數的遞歸調用08-26

C語言函數的遞歸和調用08-22

Java程序調用C/C++語言函數的方法07-31

C++調用C函數的方法05-21

C語言的可變參數問題08-23

java調用c函數的實例09-16

C語言程序的可讀性和函數的調用09-09

C++如何調用matlab函數06-29

C語言函數的參數和返回值09-14

主站蜘蛛池模板: 嘉禾县| 涿州市| 五指山市| 桃源县| 礼泉县| 桐庐县| 龙里县| 桓仁| 兴仁县| 阿荣旗| 怀化市| 靖边县| 集贤县| 土默特右旗| 开远市| 巨鹿县| 普洱| 抚松县| 泰安市| 巫溪县| 白朗县| 寻甸| 札达县| 萨迦县| 永昌县| 花莲县| 桑日县| 慈利县| 嵊泗县| 龙岩市| 广德县| 顺昌县| 巴林右旗| 淄博市| 建德市| 综艺| 康乐县| 闻喜县| 中西区| 余庆县| 平江县|