栈帧(Stack Frame)

0x01.栈在计算机中的应用
在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值,是由系统自动分配的,一般速度较快;存储地址是连续且存在有限栈容量,会出现溢出现象,程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使栈减小。
栈用于维护函数调用的上下文,离开了栈,函数调用就没法实现。
栈是从高地址向低地址延伸。

0x02.栈帧和栈帧的结构
每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame)。

一个函数的栈帧用ebp 和 esp 这两个寄存器来划定范围。

栈帧包括:

1.函数的返回地址和参数。
2.临时变量。 包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
3.栈帧状态值:ebp (帧指针),指向当前的栈帧的底部;esp(栈指针) 始终指向栈帧的顶部;

栈帧从低到上依次是(从高地址到低地址的方向):

1.参数
2.返回地址
3.ebp
4.局部变量
5.esp
0x03.函数的调用过程

 

调用约定
 函数调用约定描述了函数传递参数方式和栈帧同工作的技术细节。不同的操作系统、不同的语言、不同的编译器在实现函数调用时的原理虽然基本相同,但具体的调用约定还是有差别的。这包括参数传递方式,参数入栈顺序是从右向左还是从左向右,函数返回时恢复堆栈平衡的操作在子函数中进行还是在母函数中进行。
同一段代码用不同的编译选项、不同的编译器编译链接后,得到的可执行文件会有很多不同。

 

调用过程
参数入栈。将参数按照一定的顺序入栈。
返回地址入栈。将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行。
代码区跳转。处理器从当前代码区跳转到被调用函数的入口处。
栈帧处理步骤:EBP入栈,保存当前栈帧状态值,已备后面恢复本栈帧时使用。push ebp
栈帧处理步骤:ESP值赋给EBP,更新栈帧底部。mov ebp,esp
栈帧处理步骤:给新栈帧分配空间。sub esp,xxx

0x04.函数的返回过程
保存被调用函数的返回值到 eax 寄存器中。mov eax,xxx
恢复 esp 同时回收局部变量空间。mov esp, ebp
将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复出上一个栈帧。pop ebp
弹出当前栈顶元素,从栈中取到返回地址,并跳转到该位置 ret

0x05.图示

(图片转载自https://www.cnblogs.com/clover-toeic/p/3755401.html

0x06.x86和x64在栈帧上的区别

0x01:寄存器分配的不同

970b029b37c7d260eb22a2113181dc4f.png

(1)64位有16个寄存器,32位只有8个。但是32位前8个都有不同的命名,分别是e _ ,而64位前8个使用了r代替e,也就是r _。e开头的寄存器命名依然可以直接运用于相应寄存器的低32位,而剩下的寄存器名则是从r8 - r15,其低位分别用d、w、b指定长度;

(2)32位使用栈帧来作为传递的参数的保存位置,而64位使用寄存器,分别用rdi,rsi,rdx,rcx,r8,r9作为第1-6个参数,rax作为返回值;

(3)64位没有栈帧的指针,32位用ebp作为栈帧指针,64位取消了这个设定,rbp作为通用寄存器使用;

(4)64位支持一些形式的以PC相关的寻址,而32位只有在jmp的时候才会用到这种寻址方式;

0x02:(新增)汇编指令的不同

a77bc4ec7abca8991589b98615142f3d.png

mov、push、pop扩展了movq系列的mov和pushq以及popq用来操作quad word。

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值