• 汇编栈帧


    本文转载于https://www.jianshu.com/p/b666213cdd8a

    一:esp寄存器和ebp寄存器

    (1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。esp 寄存器又被称为栈指针(Stack Pointer);

    (2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。ebp 寄存器又被称为帧指针(Frame Pointer);

      在x86-x64系统中栈的方向是向下生长的,现在以64位操作系统为例举例。

      push  eax    #esp=esp-8

      pop eax      #esp=esp+8

      sub esp,32  #esp=esp-32(栈扩大32个字节)

      add esp,32 #esp=esp+32(栈缩小32个字节)

    二:栈

      在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值,是由系统自动分配的,一般速度较快;存储地址是连续且存在有限栈容

      量,会出现溢出现象程序可以将数据压入栈中,也可以将数据从栈顶弹出。压栈操作使得栈增大,而弹出操作使栈减小。栈用于维护函数调用的上下文,离开了栈函数调用就没法实现。

    三:栈帧

      每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame).每个独立的栈帧一般包括:

      1.函数的返回地址和参数。

      2.临时变量: 包括函数的非静态局部变量以及编译器自动生成的其他临时变量。

      3.函数调用的上下文。

      4.一个函数的栈帧用ebp 和 esp 这两个寄存器来划定范围.ebp 指向当前的栈帧的底部,esp 始终指向栈帧的顶部。

      

    在函数调用的过程中,有函数的调用者(caller)和被调用的函数(callee).
    调用者需要知道被调用者函数返回值;
    被调用者需要知道传入的参数和返回的地址;

    四:函数调用

    函数调用分为以下几步:

    • 参数入栈: 将参数按照调用约定(C 是从右向左)依次压入系统栈中;
    • 返回地址入栈: 将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行;
    • 代码跳转: 处理器将代码区跳转到被调用函数的入口处;
    • 栈帧调整: 
      1.将调用者的ebp压栈处理,保存指向栈底的ebp的地址(方便函数返回之后的现场恢复),此时esp指向新的栈顶位置; push ebp 
      2.将当前栈帧切换到新栈帧(将eps值装入ebp,更新栈帧底部), 这时ebp指向栈顶,而此时栈底就是old ebp;   mov ebp, esp

    五:函数返回

    函数返回分为以下几步:

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

    到这里栈帧以及函数的调用与返回已经结束了,这里涉及一些汇编的知道,这里还没有记录不同平台的调用约定和一些特殊的寄存器.





     
  • 相关阅读:
    git删除远程tag
    date的getTime问题
    EasyExcel读取excel文件反射成实体后全为NULL
    springboot回滚部分异常
    Java8 LocalDate、Date、LocalDateTime、时间戳的转换
    mysql未查到行,返回一条默认结果
    Maven No archetype found in remote catalog. Defaulting to internal catalog.
    HashMap相关资料
    HibernateHql
    用户名登录
  • 原文地址:https://www.cnblogs.com/ligei/p/12724889.html
Copyright © 2020-2023  润新知