针对以下代码进行分析
1 #include<iostream>
2 #include<stdio.h>
3 #include<stdlib.h>
4
5 int Calc( int a,int b,int c)
6 {
7
8
9 c=12;
10 b=11;
11 a=10;
12 int d;
13 int e;
14 int f;
15 int g;
16 g=a+b+c+d+e+f;
17 return a+b+c;
18 }
19 int main( int argc,char **argv )
20 {
21
22 int a=16,b=32,c=48;
23 int d=0;
24 int e=4;
25 int f=8;
26 int g=9;
27 int m=Calc(a,b,c);
28 return 0;
29
30
31 }
首先进行编译 不使用编译器 优化选项-O1,-O2,-O3,也不进行debug编译,关闭-g选项:
g++ aa.cpp aa -o aa
gdb aa
输入汇编命令:
查看calc函数的汇编源码
(gdb) disassemble /m Calc
Dump of assembler code for function Calc(int, int, int):
6 {
0x000000000000073a <+0>: push %rbp
0x000000000000073b <+1>: mov %rsp,%rbp
0x000000000000073e <+4>: mov %edi,-0x14(%rbp)
0x0000000000000741 <+7>: mov %esi,-0x18(%rbp)
0x0000000000000744 <+10>: mov %edx,-0x1c(%rbp)
7
8
9 c=12;
0x0000000000000747 <+13>: movl $0xc,-0x1c(%rbp)
10 b=11;
0x000000000000074e <+20>: movl $0xb,-0x18(%rbp)
11 a=10;
0x0000000000000755 <+27>: movl $0xa,-0x14(%rbp)
12 int d;
13 int e;
14 int f;
15 int g;
16 g=a+b+c+d+e+f;
0x000000000000075c <+34>: mov -0x14(%rbp),%edx
0x000000000000075f <+37>: mov -0x18(%rbp),%eax
0x0000000000000762 <+40>: add %eax,%edx
0x0000000000000764 <+42>: mov -0x1c(%rbp),%eax
0x0000000000000767 <+45>: add %eax,%edx
0x0000000000000769 <+47>: mov -0x10(%rbp),%eax
0x000000000000076c <+50>: add %eax,%edx
0x000000000000076e <+52>: mov -0xc(%rbp),%eax
0x0000000000000771 <+55>: add %eax,%edx
0x0000000000000773 <+57>: mov -0x8(%rbp),%eax
0x0000000000000776 <+60>: add %edx,%eax
0x0000000000000778 <+62>: mov %eax,-0x4(%rbp)
17 return a+b+c;
0x000000000000077b <+65>: mov -0x14(%rbp),%edx
0x000000000000077e <+68>: mov -0x18(%rbp),%eax
0x0000000000000781 <+71>: add %eax,%edx
0x0000000000000783 <+73>: mov -0x1c(%rbp),%eax
0x0000000000000786 <+76>: add %edx,%eax
18 }
0x0000000000000788 <+78>: pop %rbp
0x0000000000000789 <+79>: retq
End of assembler dump.
(gdb)
其中calc函数里面的栈结构如下图
Calc函数栈结构 | |
地址 | 存储内容 |
addr-> | rbp |
-4 | g |
-8 | f |
-12 | e |
-16 | d |
-20 | a |
-24 | b |
-28 | c |
-32 | ret addr |
(gdb) disassemble /m main
Dump of assembler code for function main(int, char**):
20 {
0x000000000000078a <+0>: push %rbp
0x000000000000078b <+1>: mov %rsp,%rbp
0x000000000000078e <+4>: sub $0x30,%rsp
0x0000000000000792 <+8>: mov %edi,-0x24(%rbp)
0x0000000000000795 <+11>: mov %rsi,-0x30(%rbp)
21
22 int a=16,b=32,c=48;
0x0000000000000799 <+15>: movl $0x10,-0x20(%rbp)
0x00000000000007a0 <+22>: movl $0x20,-0x1c(%rbp)
0x00000000000007a7 <+29>: movl $0x30,-0x18(%rbp)
23 int d=0;
0x00000000000007ae <+36>: movl $0x0,-0x14(%rbp)
24 int e=4;
0x00000000000007b5 <+43>: movl $0x4,-0x10(%rbp)
25 int f=8;
0x00000000000007bc <+50>: movl $0x8,-0xc(%rbp)
26 int g=9;
0x00000000000007c3 <+57>: movl $0x9,-0x8(%rbp)
27 int m=Calc(a,b,c);
0x00000000000007ca <+64>: mov -0x18(%rbp),%edx
0x00000000000007cd <+67>: mov -0x1c(%rbp),%ecx
0x00000000000007d0 <+70>: mov -0x20(%rbp),%eax
0x00000000000007d3 <+73>: mov %ecx,%esi
0x00000000000007d5 <+75>: mov %eax,%edi
0x00000000000007d7 <+77>: callq 0x73a <Calc(int, int, int)>
0x00000000000007dc <+82>: mov %eax,-0x4(%rbp)
28 return 0;
0x00000000000007df <+85>: mov $0x0,%eax
29
30
31 }
0x00000000000007e4 <+90>: leaveq
0x00000000000007e5 <+91>: retq
End of assembler dump.
其中main函数里面的栈结构如下图
main函数栈结构 | |
地址 | 存储内容 |
addr-> | rbp |
-4 | m |
-8 | g |
-12 | f |
-16 | e |
-20 | d |
-24 | c |
-28 | b |
-32 | a |
-36 | argc |
-40 | argv |
-44 | ret addr |
原理:
stdcall或者cdecl方式函数调用的时候,分配栈帧空间,按照顺序:
参数:从右往左入栈
局部变量:从上到下,从左到右
栈底=返回地址
问题来了,都说栈是从上到下(高地址到低地址生长) 为什么我实验得出来的结论参数是相反的?
还是说栈是从高到低只是指空间从高到低,和参数顺序是两个概念?