什么是栈帧

article/2025/10/18 22:12:02

栈帧浅析

什么是栈帧

引用百度百科中的解释:

栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。

函数的每次调用,都有它自己独立的栈帧。栈帧中维持着函数调用所需要的各种信息,包括函数的入参、函数的局部变量、函数执行完成后下一步要执行的指令地址、寄存器信息等。

运行时栈

栈帧使用了栈这一数据结构,达到了后进先出(First In Last Out)的内存管理原则。不管是插入数据还是删除数据,都是在栈顶进行的。

x86-64的栈由高地址向低地址增长,寄存器rbp指向当前栈帧的底部(高地址),寄存器rsp指向当前栈帧的顶部(低地址)。数据压栈和出栈会修改rsp的值。通过push指令将数据存入栈中,同时64位系统中会对栈顶指针做减法操作rsp=rsp-8pop指令是push的逆操作,它将数据从栈中读取出来,同时64位系统中会对栈顶指针做加法操作rsp=rsp+8

当过程P调用过程Q时,

  1. 把实参压栈,cdeclgcc的默认调用约定,实参压栈顺序为从右至左

  2. 把返回地址(即P调用Q后的下一条指令地址)压入栈中,表示当Q返回后,P程序下一步要从哪条指令开始运行

  3. 开始调用Q,首先将P的栈底rbp压栈,然后栈顶rsp赋值给rbp,从而形成新的栈底地址。我们在看函数调用的汇编代码时经常看到的一段正是在做这个操作

    push    rbp
    mov     rbp, rsp
    
  4. 分配局部变量空间,开始具体执行Q函数的指令代码
    在这里插入图片描述

转移控制

将控制从函数P转移到函数Q只需要将程序计数器(PC)设置为Q函数代码的起始位置。另外,稍后从Q返回时处理器还需要继续执行P的下一条指令A。在x86-64中,这个过程是用执行call Q指令来完成的。该指令将A的地址压栈,并将PC设置为Q的起始地址。

Q执行完成后弹出A地址这个过程是通过ret指令完成的,它会弹出地址A,并把PC设置为A

以一段函数调用为例

#include<iostream>
#include<stdint.h>int32_t Add(int32_t x,int32_t y)
{int32_t z=0;z=x+y;return z;
}int main()
{int32_t a=10;int32_t b=20;int32_t ret=Add(a,b);return 0;
}

函数很简单,我们在Compiler Explorer (godbolt.org)中编译,编译器版本为x86-64 GCC 11.2优化等级为O0,查看这段程序的汇编代码:

#include<iostream>
#include<stdint.h>int32_t Add(int32_t x,int32_t y)      //  push    rbp//  mov     rbp, rsp//  mov     DWORD PTR [rbp-20], edi//  mov     DWORD PTR [rbp-24], esi
{int32_t z=0;                      //  mov     DWORD PTR [rbp-4], 0z=x+y;                            //  mov     edx, DWORD PTR [rbp-20]//  mov     eax, DWORD PTR [rbp-24]//  add     eax, edx//  mov     DWORD PTR [rbp-4], eaxreturn z;                         //  mov     eax, DWORD PTR [rbp-4]
}                                     //  pop     rbp//  retint main()                       
{                                     //  push    rbp//  mov     rbp, rsp//  sub     rsp, 16int32_t a=10;                     //  mov     DWORD PTR [rbp-4], 10int32_t b=20;                     //  mov     DWORD PTR [rbp-8], 20int32_t ret=Add(a,b);             //  mov     edx, DWORD PTR [rbp-8]//  mov     eax, DWORD PTR [rbp-4]//  mov     esi, edx//  mov     edi, eax//  call    Add(int, int)//  mov     DWORD PTR [rbp-12], eaxreturn 0;
}

分析上述汇编代码,当main函数调用Add时,执行了以下步骤(注意执行顺序):

Add(int, int):// 5. 将main函数的栈帧底部地址入栈保存 push    rbp// 6. 将此时的栈帧顶部地址作为Add函数的栈帧底部地址mov     rbp, rsp// 7. 获取形参xmov     DWORD PTR [rbp-20], edi// 8. 获取形参ymov     DWORD PTR [rbp-24], esi// 9. 初始化z=0mov     DWORD PTR [rbp-4], 0// 10. 将x和y分别保存至寄存器edx和eax,然后相加,结果保存在寄存器eaxmov     edx, DWORD PTR [rbp-20]mov     eax, DWORD PTR [rbp-24]add     eax, edx// 11. 将寄存器eax中的x和y相加结果赋值给zmov     DWORD PTR [rbp-4], eax// 12. 将Add函数结果z保存至寄存器eaxmov     eax, DWORD PTR [rbp-4]// 13. 将之前保存的main函数栈帧底部地址出栈并保存至rbppop     rbp// 14. 相当于pop eip 将之前保存的mov     DWORD PTR [rbp-12], eax指令地址出栈并保存至eipretmain:push    rbpmov     rbp, rspsub     rsp, 16// 1. 初始化a=10mov     DWORD PTR [rbp-4], 10// 2. 初始化b=20mov     DWORD PTR [rbp-8], 20// 3. 分别将a和b保存至寄存器eax和edx,再分别拷贝至寄存器edi和dsimov     edx, DWORD PTR [rbp-8]mov     eax, DWORD PTR [rbp-4]mov     esi, edxmov     edi, eax// 4. 等价于两条命令//      ① push eip 将eip中存储的下一条指令地址压栈,即mov     DWORD PTR [rbp-12], eax这条指令//      ② jmp Add(int,int) 跳转至Add(int,int)call    Add(int, int)// 15. 将Add函数返回结果保存至retmov     DWORD PTR [rbp-12], eax

http://chatgpt.dhexx.cn/article/pqPhf89L.shtml

相关文章

【详解】函数栈帧——多图(c语言)

目录 前言 一.函数栈帧是什么&#xff1f; 二、栈帧准备知识 1.内存分区 2.什么是栈&#xff1f; 3.esp&#xff0c;ebp&#xff0c;eax寄存器 三、详解栈帧创建与销毁全过程 调用函数之前&#xff1a; 将传入函数的值放入栈中 函数执行&#xff1a; 1.保护当前ebp 2.…

【mcuclub】模数转换ADC0832

一、实物图 二、原理图 编号名称功能1CS片选使能&#xff0c;低电平芯片使能。2CH0模拟输入通道0&#xff0c;或作为IN/-使用。3CH1模拟输入通道1&#xff0c;或作为IN/-使用。4GND电源地5DI数据信号输入&#xff0c;选择通道控制。6DO数据信号输出&#xff0c;转换数据输出。7…

[技术讨论] [DDS] AD9833原理介绍及chiliDDS驱动分享(上)

​ 其实本文还有另一标题&#xff1a;《AD9833调不通&#xff1f;看这篇**就够了》 总觉字里行间隐隐霸气外露&#xff0c;不符合作者低调的风格&#xff0c;于是换了个朴素标题。标题狂不狂暂且不评&#xff0c;作者水平有限却是个事实&#xff1b;看到这篇**是你我缘分&…

ADC0832的使用

百度搜索ADC0832 Datasheet便可以免费获取该芯片的权威数据手册。 最重要的是查看它的时序及对应英文词组的意思。 CLK为时钟信号&#xff0c;需要外部输入&#xff0c;可直接与单片机引脚相连 Chip Select&#xff08;CS&#xff09;:从Timing图中可以看出芯片工作期间要保持…

ADC0832的AD模数转换原理及编程

✅作者简介&#xff1a;嵌入式领域优质创作者&#xff0c;博客专家 ✨个人主页&#xff1a;咸鱼弟 &#x1f525;系列专栏&#xff1a;单片机设计专栏 目录 一、描述 二、模数转换原理&#xff1a; 三、模数转换的过程&#xff1a; 四、八位串行A/D转换器ADC0832简介&…

ADC0809的使用

一、前言介绍 使用ADC0809对一个模拟电压进行转换转换后的电压使用数码管显示出来 二、ADC0809的介绍 1、ADC0809简介 ADC0809是采用COMS工艺制造的双列直插式单片8位A/D转换器。分辨率8位&#xff0c;精度7位&#xff0c;带8个模拟量输入通道&#xff0c;有通道地址译码锁…

基于STM32F103RCT6的AD9833驱动开发(代码可以免费发邮箱)

基于STM32F103RCT6的AD9833驱动开发&#xff08;代码可以免费发邮箱&#xff09; AD9833手册分析 管脚定义&#xff1a; 手册就先讲到这里&#xff0c;不明白的欢迎评论区留言&#xff0c;另外我会把代码还有手册一并发送给感兴趣的朋友。 AD9833典型应用电路&#x…

AD9833数字信号发生器模块

简 介&#xff1a; 本文记录了使用快速制版测试AD9833这款数字信号发生器的内容。 关键词&#xff1a; AD9388&#xff0c;数字信号发生&#xff0c;快速制版 基于AD9833的正弦波&#xff0c;三角波&#xff0c;方波频率发生模块可以通过ZIGBEE来完成输入输出控制。其中还包括有…

STM32驱动AD9833模块

STM32驱动AD9833模块 前言软硬件准备一、本次使用的硬件二、代码 链接 前言 淘宝上买了个AD9833模块&#xff0c;stm32用商家的例程代码可以调频&#xff0c;可以调相&#xff0c;就是调不了幅度。换了几块不同32开发板都不行&#xff0c;重新以正点原子F103的工程为基础把驱动…

AD9833信号波形谐波

AD9833产生高频信号的谐波 ~ AD9833是一款AnalogDevices公司提供的数字信号可编程信号发生器芯片。它一般配有外置的主时钟信号&#xff0c;每次时钟信号将将内部28位的相位累加器递增一个相位数值。该相位数值由芯片SPI串口被外部的MCU设置。 相位累加器的高12位选择内部4096…

51驱动AD9833

使用51驱动AD9833模块的使用 关于AD9833相关参数程序流程代码片上传程序总结 原文链接&#xff1a;https://www.yourcee.com/newsinfo/2925703.html 关于AD9833 AD9833是一款低功耗、可编程波形发生器&#xff0c;能够产生正弦波、三角波和方波输出。各种类型的检测、信号激励…

Arduino + AD9833 波形发生器

Arduino SI5351 方波发生器_姜戈12的博客-CSDN博客SI5351 方波发生器https://blog.csdn.net/jiangge12/article/details/125815044 感觉 Si5351 只有方波还是少点意思。 看到有人做 AD9833 &#xff0c;成品卖355元。https://www.bilibili.com/video/av463721457/ 上面视频…

[技术讨论][DDS] AD9833原理介绍及chiliDDS驱动分享(上)

其实本文还有另一标题&#xff1a;《AD9833调不通&#xff1f;看这篇**就够了》 总觉字里行间隐隐霸气外露&#xff0c;不符合作者低调的风格&#xff0c;于是换了个朴素标题。标题狂不狂暂且不评&#xff0c;作者水平有限却是个事实&#xff1b;看到这篇**是你我缘分&#xff…

STM32单片机TFT显示AD9833 DDS信号发生器语音播报正弦波方波三角波

实践制作DIY- GC0146---TFT显示AD9833 DDS信号发生器 基于STM32单片机设计---TFT显示AD9833 DDS信号发生器 二、功能介绍&#xff1a; 硬件组成&#xff1a;STM32F103C系列最小系统板 1.8寸TFT彩屏AD9833信号模块4*4矩阵键盘DY-SV17F语音播报模块 1.通过4*4键盘来设定频率值和…

失真很大的波形发生器AD9833

波形发生器AD9833 01 波形发生器 一、AD9833 AD9833是一款AnalogDevices公司提供的数字信号可编程信号发生器芯片。 它一般配有外置的主时钟信号&#xff0c;每次时钟信号将将内部28位的相位累加器递增一个相位数值。 该相位数值由芯片SPI串口被外部的MCU设置。  相位累加器…

【STM32+cubemx】0030 HAL库开发:DDS芯片AD9833实现简单的波形发生器

大家好&#xff0c;我是学电子的小白白&#xff0c;今天带大家了解一款波形发生器芯片——AD9833。 AD9833是AD公司出品的一款DDS波形发生器&#xff0c;能够产生正弦波、三角波和方波输出。 1&#xff09;什么是DDS 通俗来讲&#xff0c;DDS是一种把波形预先存储在芯片内部的…

2.电赛进行时......(AD9833(DDS)模块的学习使用)

文章目录 前言一、DDS是什么&#xff08;信号发生器&#xff09;&#xff1f;二、AD9833模块介绍1.概述2.模块移植3、效果展示![在这里插入图片描述](https://img-blog.csdnimg.cn/2b0d29939275403f9248339c894965a0.png#pic_center) 前言 如果是玫瑰&#xff0c;它总会开花的…

AD9833介绍与应用(C语言实现)

1.特性 低功耗、可编程波形发生器&#xff0c;能产生正弦波、三角波和方波的输出&#xff1b; 主频时钟为25MHz时&#xff0c;可实现0.1Hz的分辨率&#xff1b;主频时钟为1MHz时&#xff0c;可实现0.004Hz的分辨率&#xff1b; 三线式串行接口(SDATA、SCLK、FSYNC)写入数据&a…

2021电赛预测—手把手带你玩转DDS模块AD9833

1、电赛预测 摘要&#xff1a;原定于7月28日才发布的器件清单&#xff0c;提前2天在26号就发布。感觉大家现在应该猜题预测&#xff0c;与其猜题&#xff0c;还不如静下心来做题。盲目猜题是没有必要的&#xff0c;熟悉相关器件倒尤为重要。不要到处去水群聊天&#xff0c;听风…

幻方....

c语言上机。。。。 c写的幻方。 1 /*************************************************************************2 > File Name: code/class/7.c3 > Author: 111qqz4 > Email: rkz2013126.com 5 > Created Time: 2015年11月11日 星期三 19时31分5…