函数调用过程

函数调用大致包括以下几个步骤:
1.参数入栈 比如有三个参数

push arg3
push arg2
push arg1

2.返回地址入栈 代码去跳转

call target_addr

call指令 相当于

push EIP
jmp target_addr

就是把将当前指令地址压入栈中,跳转到函数入口处。
此时esp指向 返回地址

3.栈帧调整

push ebp
mov ebp,esp
sub esp,xxx

将当前栈帧的基址ebp入栈,此时esp指向了当前栈帧的基址esp,然后
mov ebp,esp
sub esp,xxx
调高栈底,申请新的栈空间。

所以在进入函数后,ebp指向的是前栈帧的基址,ebp+4 指向的是返回地址 ebp+8 指向的是arg1

栈结构如下:

xx———————当前esp指向这里 这里假设申请了12个字节
xx
xx
前栈帧的ebp———当前ebp指向指向这里
返回地址eip
arg1
arg2
arg3


函数的返回过程:
1.弹出当前的栈帧,恢复栈平衡
2.跳转eip

1.add esp,xxx 降低栈顶
2.
pop ebp 将当前的esp指向的 前栈帧的ebp 恢复到ebp中, 也就是恢复栈基址
retn

retn的功能:弹出栈顶元素 到eip中,恢复调用前的代码区。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
函数调用过程是程序中常见的一种操作,它通常涉及到参数传递、栈帧的建立与销毁、返回值的传递等多个方面。从汇编的角度来看,函数调用过程可以分为以下几个步骤: 1. 将函数的参数压入栈中。在调用函数时,需要将函数所需的参数传递给它。这些参数通常以一定的顺序压入栈中,以便在函数内部使用。在 x86 架构中,参数的传递是通过将参数压入栈顶实现的。 2. 调用函数。函数调用的指令通常是 CALL 指令。在调用函数前,需要将函数的入口地址压入栈中,以便在函数执行完毕后返回到调用位置。CALL 指令会将当前的程序计数器(PC)压入栈中,并将函数的入口地址作为新的 PC。 3. 建立栈帧。在函数被调用时,需要为函数建立一个独立的栈帧,以便在函数内部使用局部变量和临时变量。栈帧通常包括以下几个部分:返回地址、旧的基址指针、局部变量和临时变量。在 x86 架构中,栈帧的建立是通过将 ESP 寄存器减去一个固定的值实现的。 4. 执行函数。在函数被调用后,CPU 会跳转到函数的入口地址并开始执行函数。函数内部可以通过栈中的参数和局部变量完成相应的计算和操作。 5. 返回值传递。在函数执行完毕后,需要将函数的返回值传递给调用者。在 x86 架构中,函数的返回值通常通过 EAX 寄存器传递。 6. 销毁栈帧。在函数执行完毕后,需要将栈帧销毁,以便释放栈空间。栈帧的销毁通常是通过将 ESP 寄存器还原到旧的基址指针处实现的。 7. 返回到调用位置。在函数执行完毕后,需要返回到函数被调用的位置。在 x86 架构中,返回指令通常是 RET 指令。RET 指令会将栈顶的返回地址弹出,并将其作为新的 PC。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值