一览
本文目的
之前,我本想观察函数调用时,栈的细节。顺便验证一下,口口相传的,C/C++从右向左入栈。详情参考之前的文章:C++函数调用栈细节(gdb调试)结果发现了些出乎意料的情况。
在x86-64 gcc 5.4.0 没有优化选项时
代码:
1 #include<stdio.h>
2
3 class A {
4 public:
5 int f;
6 int s;
7 };
8
9 int sum(int l,int r)
10 {
11 int res =0;
12 res = l+r;
13 return res;
14 }
15 int main ()
16 {
17 A a;
18 a.f = 0x55;
19 a.s = 0x66;
20 int res = sum(a.f,a.s);
21 printf("sum: %d",res);
22 return 0;
23 }
出现了:
- 调用函数前参数没有入栈,而是按照从右向左的顺序存放在了寄存器。
- 进入调用函数后,参数从寄存器存放进了栈中,但是按照从左到右的顺序。
- 进入调用函数后rsp栈顶指针没有增长,第2条里的参数存放在了栈顶之外。
以上三条可以在C++函数调用栈细节(gdb调试)中看到调试的具体情况。
x86-64下打印参数地址判断参数入栈顺序的做法不合理
之前看过很多判断参数入栈顺序,通过打印参数的地址,根据右边参数为高地址,左边参数为低地址,就得出参数是从右向左入栈。但是在x86-64下,这样行不通。
1 #include<stdio.h>
2
3 void foo(int x, int y)
4 {
5 printf("x = %d at [%X]\n", x, &x);
6 printf("y = %d at [%X]\n", y, &y);
7 }
8
9 int main ()
10 {
11 foo(100,300);
12 return 0;
13 }
不添加优化选项编译
结果:
左边参数地址高于右边参数地址。
难道这就说明了 参数从左向右入栈的?有些偏颇。
情况1:函数调用参数从右向左存放到寄存器,又从左到右存放到栈
0000000000400526 <foo>:
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: 48 83 ec 10 sub $0x10,%rsp 栈顶有增长
40052e: 89 7d fc mov %edi,-0x4(%rbp) edi即左边参数100,先存放在高地址(靠近栈底)
400531: 89 75 f8 mov %esi,-0x8(%rbp) esi即右边参数300,后存放在低地址
400534: 8b 45 fc mov -0x4(%rbp),%eax
400537: 48 8d 55 fc lea -0x4(