• 栈的调用方式


    从可执行文件说起

    程序可以被分成三段(部分):
    指令、数据和函数。

    elf可执行文件的分段:
    文件头,包含文件的类型等信息。
    数据段,静态数据,包括全局变量和静态变量;
    代码段,要执行的指令;
    栈,除了栈是自顶向下增长外,其他模型都是自底向上增长。
    堆,程序员自己管理的数据区域。

    所以程序在内存中的存储,并不是按写的时候那样存放,而是数据放一起,指令放在一起,函数调用放在一起。

    汇编基础

    %是寄存器,如%edx
    $是常量,比如$0x1;
    ()是内存,比如(%edx)

    push是将ebp寄存器的值存到内存;
    pop是将esp内存的值存到寄存器。

    ebp是栈底指针;
    esp是栈顶指针。

    函数调用的基本操作:
    1.跳转到函数调用地址;
    2 建立新栈帧;
    3.存储局部变量;

    那么堆栈后,怎么修改临时变量呢?
    比如a=0;存入栈中,一顿堆栈,
    此时a=1;那么要通过栈底指针ebp索引变量a的数据,并通过mov赋值。

    栈的作用

    栈用来存储:

    • 函数的返回地址和参数
    • 局部变量,不包括静态变量
    • 上下文,函数调用前后需要保持不变的寄存器

    1)push操作先移动栈顶指针,之后将信息入栈。
    2)esp为堆栈指针,栈顶由esp寄存器来定位。压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大。
    3)ebp是32位的bp,是基址指针。bp为基指针寄存器,用它可直接存取堆栈中的数据,它在调用函数时保存esp,以便函数结束时可以正确返回。
    4)默认的函数内部变量的压栈操作为:从上到下、从左向右,采用4字节对齐。数组压栈方法略有不同,即从最后一个元素开始,直到起始元素为止,即采用从右向左的方法压栈。

    压栈操作是4字节对齐,所以即使压入的是char类型,也占用4字节

    每个函数在调用前都会做一件事情。
    (1)把调用方的ebp入到自己的栈里去
    (2)用esp指向新的栈顶位置,把esp的值赋给ebp,产生新的ebp
    (3)开辟空间,初始0XCCCCCCCC。
    ebp入栈,实参入栈,形参入栈,调用call指令。call有两步,把下一行指令的地址入栈,跳转到调用的函数执行。形参内存主调方开辟,主调方释放。

  • 相关阅读:
    [附源码]Python计算机毕业设计大学生心理健康管理系统
    Vue生命周期
    基于JAVA医院患者管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
    世界互联网大会|云轴科技ZStack受邀分享云原生超融合
    concrt140.dll怎么下载,concrt140.dll修复工具(修复精灵下载)一键修复问题
    拓尔微电子超低功耗电源芯片解决方案
    渗透测试--3.中间人攻击
    C#语言基础速成Day07
    周老师话职称(陕西省职称申报好处)
    《实现领域驱动设计》-聚合
  • 原文地址:https://blog.csdn.net/weixin_39759247/article/details/126054389