函数调用过程

本文深入解析函数调用的汇编级过程,包括参数入栈、寄存器保存与恢复、局部变量的生命周期及函数返回机制。通过具体实例,详细说明了计算机堆栈结构如何辅助函数调用与执行。

主要流程:

调用前的准备 —— 参数入栈,eip 入栈,ebp 入栈,eip跳转

函数执行

恢复到调用前状态 —— 返回值 eax,恢复ebp,恢复 eip

#include <stdio.h>

int f(){
    int a=1;
    return a;
}

int main() 
{
  int b=f();//汇编  call  f (0B711D6h)
  return 0;
}


call  f (0B711D6h)

pushl	%ebp

movl	%esp, %ebp

subl	$16, %esp

。。。

movl %ebp %esp

pop %ebp

ret

这些是函数调用的必经步骤!

看懂这个之前还得先了解计算机的堆栈结构

一:计算机一般是小端——储存顺序和常识相反(仅供理解)

即 高地址(栈底)—————— 低地址(栈顶)
在这里插入图片描述
ebp 和 esp 是两个寄存器,分别保存栈底指针和栈顶指针(地址)

二:栈——相当于往有底的杯子里倒水

在这里插入图片描述

那么,上面的汇编语句就可以开始解析了

首先:

call  f (0B711D6h)

零:call 语句 —— eip 入栈,eip跳转

(eip —— 保存了下一条即将要执行语句的地址)

eip 入栈——记录当前语句执行到哪了,之后好恢复

eip跳转 ——跳转到要调用的函数处

(通过括号内的地址实现跳转,这个地址是编译器给的)

在这里插入图片描述

一:push ebp 保存原先栈底

入栈前:
在这里插入图片描述
然后 push 指令—— esp 往低地址移动4个字节

( esp 的值为4字节)

然后把 ebp 的值存到 esp 所指的空间
在这里插入图片描述

(指针所指的是数据的起始地址,从低地址开始)

Ps:
因为计算机是小端,所以才会有东西从栈底进的感觉

其实,在栈顶存入新元素,这其实就是入栈 push

这里一定要好好理解!!!!

二:movl %esp, %ebp 得到新栈底

把 esp 的值赋给ebp

在这里插入图片描述
这时 esp 和 ebp 指向同一地址

( 这里是寄存器之间的赋值!)

三:subl $16, %esp 得到新栈顶

esp 减16 的实际意义

—— 把esp从高地址往低地址移动,从而有:

在这里插入图片描述

栈顶和栈顶分开,形成了新的栈

——他们之间就可以做好多事情了

Ps:
他们之间的并不是函数内容

函数语句转成的汇编语句存在内存的其他地方

他们之间存的一般是我们口中的局部变量~

正是因为调用函数时用的栈是临时的

函数执行完之后,ebp 和 esp 恢复到原先的值

局部变量的生命周期也就结束了~

(在内存中的值可能不变,但是已经访问不了了)

这里举个例子吧:

int f(){
    int a=1;
    return a;
}
// 赋值语句对应汇编语句: movl	$1, -4(%ebp)

在这里插入图片描述
栈中存的 1 就是我们说的局部变量啦

(函数结束后,ebp esp 转移,局部变量就无效咯~)

最后是函数调用的结束处理

int f(){
    int a=1;
    return a;
}
 
//return a 对应的汇编语句 
movl -4(%ebp), %eax 
//把a的值赋到eax寄存器中

return 返回值其实就保存在 eax 寄存器中

接下来,把 esp 和 ebp 的值还原回去

movl %ebp %esp

pop %ebp

ret

把 ebp 的值赋给 esp
在这里插入图片描述

此时,esp 和 ebp 都指向栈底那唯一的 —— “ ebp的值 ”

然后,pop 指令 —— 把栈顶指向的值(即上图的“ ebp 的值”)

赋到ebp 寄存器中

同时,esp 往高地址移动4字节(出栈了一个4字节的值嘛)

在这里插入图片描述

此时,ebp 和 esp 都回到了原本的状态

然后

ret

把返回地址出栈,并且赋值给 eip

从而返回到调用函数之前的状态


这里再提一下带参的函数调用

(在 call语句 调用函数之前先把这些参数入栈就行啦~)

(之后以 ebp 为基准就可以访问这些传进的参数了)

(参数表为: 参数1,参数2 时先参数2入栈,再参数1入栈)

后面的参数放高地址嘛,就先入栈啦~

(然后再 eip 入栈)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值