函数栈的变化过程

C++调用函数在内存管理中的过程就是新建一个函数栈,里面保存了函数返回值,寄存器的备份(rbp),局部变量,函数参数。调用结束后栈空间销毁,回到调用的函数继续执行下面的代码。

在这里插入图片描述

下面说几个要点。
首先要了解寄存器的作用。
rbp保存函数栈底指针,rsp保存函数栈顶指针,
rdi、rsi、rdx、rcx、r8、r9:调用函数时依次存放第1到第6个参数,若多于6个的参数则会被压入栈。
rip保存返回地址。
rax保存返回值。

我们从调用开始到调用结束一步步分析一下:(假设main函数调用add函数)
当我们调用函数时,栈的变化如下:
1、首先,会将原函数main函数的返回地址压入栈中,返回地址就是add函数下一条指令的地址,因为函数返回后就要执行这个指令了。
2、将原函数main的rbp栈底指针入栈,因为函数返回后还要维护main函数的栈底指针,main函数并没有执行完成。
3、将栈顶指针rsp的值赋给rbp,然后将栈顶指针减去一定的数值,为新的函数开辟空间。这里要注意,栈顶指针永远指向栈顶,所以当把rsp赋给rbp时,rbp已经指向原来main的栈顶+返回地址+main的rbp了那个位置了。

4、上面都是准备工作,接下来就是在那段空间进行一系列操作。比如存储函数参数的值(movl $1 %rbp-4就是将参数1放到栈底的上一个位置,栈是高地址向低地址增长的,所以要减),将值赋给寄存器等。如果有返回值,返回值会放到eax寄存器中。
5、栈中弹出main函数栈的rbp地址,赋值给rbp寄存器,即恢复main函数的rbp.
6、leave,RET退出调用。ret指令则是将栈顶的返回地址弹出到EIP,然后按照EIP此时指示的指令地址继续执行程序。leave指令相当于将rbp赋给rsp,并把rbp出栈,将里面的值赋给rbp寄存器(相当于步骤5)
可以看到5,6和2,1是配对的,因为栈是后进先出。
7.最后还可能有返回值,从eax取出赋给main函数的局部变量处,将eax置零。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值