码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 函数栈帧的创建与销毁剖析


    目录

    一、前言

    二、基础知识介绍

    2.1 寄存器介绍

    2.2、汇编指令介绍

    三、函数栈帧的创建销毁过程

    3.1 调用main函数的函数

    3.2 main函数开辟栈帧

    3.3 在main函数中创建变量

    3.4 调用Add函数前的准备

    3.5 为Add函数开辟栈帧

    3.6 在Add函数中创建变量并运算

    3.7 Add函数栈帧的销毁

    3.8 返回main函数栈帧


    一、前言

    在C语言的过程中,我们心中难免有一些懵懂的地方。譬如:

    1.局部变量到底是怎么在栈上创建的?

    2.为什么局部变量不初始化为随机值?

    3.函数是怎么传参的?传参的先后顺序是什么?

    4.形参和实参是什么关系?

    5.函数调用是怎么实现的?

    6.函数调用后是怎么返回的?   

    学习完函数栈帧的创建与销毁,想必就能有一个比较清晰的认识了

    本文的调试结果是使用vs2013和vs2019反汇编调试而出的,不同编译器函数栈帧的创建销毁过程略有不同,具体细节取决于编译器的实现。(越高级的编译器封装越好,越不易观察学习)

    二、基础知识介绍

    2.1 寄存器介绍

    寄存器名称功能
    eax    累加器,是多数加法乘法指令的缺省寄存器
    ebx基地址寄存器,在内存寻址时存放基地址
    ecx计数寄存器,用于循环操作,比如重复的字符存储操作,或者数字统计
    edx作为eax的溢出寄存器,总是被用来放整数除法产生的余数
    esi

    源变址寄存器,主要用于存放存储单元在段内的偏移量

    通常在内存操作指令中作为“源地址指针”使用

    edi目的变址寄存器,主要用于存放存储单元在段内的偏移量
    eip控制寄存器,存储CPU下次所执行的指令地址(存放指令偏移地址)
    esp

    栈指针寄存器(extended stack pointer),其内存放着一个指针。

    该指针永远指向栈最上面一个栈帧的栈顶。esp用于堆栈操作,被形象地称为栈顶指针。

    ebp

    基址指针,指栈的栈底指针。基址指针寄存器(extended base pointer)。

    一般与esp配合使用,其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部

    2.2、汇编指令介绍

    指令名称作用
    push进栈指令将源操作数压入栈中
    pop弹栈指令从栈中弹出双字或字数据至目的操作数中
    mov传送指令把一个字节、字、或双字从源操作数传送至目的操作数
    add加法指令目的操作数加源操作数,结果送至目的操作数
    sub减法指令目的操作数减源操作数,结果送至目的操作数
    lea取有效地址指令将源操作数的有效地址传送到通用寄存器
    call过程调用指令程序下一条指令的位置的地址压入堆栈中,并转移到调用的子程序
    ret段内过程返回指令从调用过程返回,继续执行主程序。
    jmp无条件转移指令使程序无条件地转移到指令规定的目的地址去执行指令

    字(word):表示两个字节长度的数值      双字(dword):表示四个字节长度的数值

    三、函数栈帧的创建销毁过程

    接下来使用下述代码进行演示 (语句简单,易于观察)

    1. #include
    2. int Add(int x, int y)
    3. {
    4. int z = 0;
    5. z = x + y;
    6. return z;
    7. }
    8. int main()
    9. {
    10. int a = 10;
    11. int b = 20;
    12. int c = 0;
    13. c = Add(a, b);
    14. printf("%d\n", c);
    15. return 0;
    16. }

    3.1 调用main函数的函数

    vs2013进入调试,打开窗口中的调用堆栈,F10不断调试,得到下图

    可以发现main函数也是由别的函数(__tmainCRTStartup函数)调用的,而__tmainCRTStartup函数则是由mainCRTStartup函数调用的。

    3.2 main函数开辟栈帧

    3.3 在main函数中创建变量

    在main函数开辟的栈帧中创建变量

    3.4 调用Add函数前的准备

    3.5 为Add函数开辟栈帧

    3.6 在Add函数中创建变量并运算

    3.7 Add函数栈帧的销毁

    3.8 返回main函数栈帧

  • 相关阅读:
    励磁工作原理
    【100个 Unity实用技能】| 关于触发器互相检测的必要前提条件配置
    【零基础入门SpringMVC】第一期——开篇导论
    LVS集群
    pg 数据库,在新增的数据的时候,根据字段唯一性去更新数据
    MyBatis-Plus + Spring Boot入门案例
    《羊了个羊》H5游戏开发挑战,3小时LAYA引擎制作核心玩法
    【面试题】JS基础-异步
    优雅而酷炫的自定义CSS滚动条:展示
    中文编程开发语言工具编程实际案例:美发店会员管理系统软件编程实例
  • 原文地址:https://blog.csdn.net/GG_Bruse/article/details/127719843
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号