Linux 函数调用过程解析

一、Linux 函数调用过程解析

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

1、什么是栈帧?

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

Linux 函数调用过程解析_第1张图片

2、函数调用过程解析

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

#include 

 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函数对应的反汇编指令

Linux 函数调用过程解析_第2张图片

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

在这里插入图片描述

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

在这里插入图片描述

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

Linux 函数调用过程解析_第3张图片

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

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

Linux 函数调用过程解析_第4张图片

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

Linux 函数调用过程解析_第5张图片

你可能感兴趣的:(Linux,汇编编程,c语言,c++,算法)