Linux 函数调用过程解析

一、Linux 函数调用过程解析

在x86的计算机系统中,内存空间中的栈主要用于保存函数的参数,返回值,返回地址,本地变量等。一切的函数调用都要将不同的数据、地址压入或者弹出栈。因此,为了更好地理解函数的调用,需要先来看看栈是怎么工作的。

1、什么是栈帧?

栈帧,也就是stack frame,其本质就是一种栈,只是这种栈专门用于保存函数调用过程中的各种信息(参数,返回地址,本地变量等)。栈帧有栈顶和栈底之分,其中栈顶的地址最低,栈底的地址最高,SP(栈指针)就是一直指向栈顶的。在x86-64bit中,用 %rbp 指向栈底,也就是基址指针;用 %rsp 指向栈顶,也就是栈指针。下面是一个栈帧的示意图:

在这里插入图片描述

2、函数调用过程解析

下面是对应的C语言代码:

#include <stdio.h>

 int add(int n1, int n2)                                                                                                                                                       
 {
     int n = n1 + n2;
     return n;
 }

 int test(int a, int b)
 {
     int n1 = 30;
     int n2 = 40;
     return add(n1, n2);
 }

 int main()
 {
     printf("ret=%d\n", test(10, 20));
     return 0;
 }

下面是main与test函数对应的反汇编指令

在这里插入图片描述

main函数调用test函数,所有函数开头的两行指令都是一样的,例如:

在这里插入图片描述

先压入main栈帧的栈基址,然后移动栈基址使它指向和栈指针同样的位置。此时产生了test的栈

在这里插入图片描述

移动test函数的栈顶指针,为test分配24个字节的栈空间,操作之后的栈空间如下:

在这里插入图片描述

test函数执行完返回,函数执行完毕一般会执行下面两条指令

执行完leaveq指令,恢复函数调用者对应的堆栈,下面是执行完leave对应的栈空间,如下:

在这里插入图片描述

执行完leave指令后会执行ret指令,将栈顶的返回地址弹出到EIP,然后按照EIP此时指示的指令地址继续执行程序,执行完ret指令后的栈帧如下:

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值