linux栈调用原理

19 篇文章 3 订阅

针对以下代码进行分析

      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
-4g
-8f
-12e
-16d
-20a
-24b
-28c
-32ret 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
-4m
-8g
-12f
-16e
-20d
-24c
-28b
-32a
-36argc
-40argv
-44ret addr

原理:

stdcall或者cdecl方式函数调用的时候,分配栈帧空间,按照顺序:

参数:从右往左入栈

局部变量:从上到下,从左到右

栈底=返回地址

问题来了,都说栈是从上到下(高地址到低地址生长) 为什么我实验得出来的结论参数是相反的?

还是说栈是从高到低只是指空间从高到低,和参数顺序是两个概念?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值