历史上的今天
今天是:2025年12月19日(星期五)
2022年12月19日 | 加深初学者对单片机堆栈的理解--分析
2022-12-19 来源:zhihu
看关于单片机方面的书籍的时候,总是能看到别人说的一些堆栈啊什么的操作,之前看到这个术语就直接跳过,没想到去探究单片机内部的原理。但是最近课程学习微机原理这门课,需要我们写汇编程序,汇编里面经常遇到堆栈这个东西,所以就找了个时间把堆栈给彻底的搞一下。
如果了解一点汇编编程话,就可以知道,堆栈是内存中一段连续的存储区域,用来保存一些临时数据。通常用来保存CALL指令调用子程序时的返回地址,RET指令从堆栈中获取返回地址。中断指令INT调用中断程序时,将标志寄存器值、代码段寄存器CS值、指令指针寄存器IP值保存在堆栈中。
堆栈也可以用来保存其他数据。
堆栈操作由PUSH,POP两条指令来完成;
堆栈操作的操作数均为子类型(两个字节)进行操作。
程序内存可以分为几个区,栈区(stack),堆区(Heap),全局区(static),文字常亮区,程序代码区。
程序编译之后,全局变量,静态变量已经分配好内存空间,在函数运行时,程序需要为局部变量分配栈空间,当中断来时,也需要将函数指针入栈,保护现场,以便于中断处理完之后再回到之前执行的函数。
栈是从高到低分配,堆是从低到高分配。
我们一般说的堆栈指的栈。堆栈又分硬堆栈和软堆栈,硬堆栈即SP,从片内RAM的顶部向下生长。软堆栈在硬堆栈跟全局变量区之间的空间,C51函数调用通过R0-R7和栈来实现。
为什么单片机启动时,不需要用bootloader将代码从ROM搬移到RAM,而ARM则需要。这里我们可以先看看单片机程序执行的过程,单片机执行分三个步骤,取执行---分析指令----执行指令。取指令的任务是:根据PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从RAM存取相关数据。要知道RAM取数的速度是远高于ROM的,但是单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。而ARM不同,cpu运行的频率高,远大于从ROM读写的速度,所以一般有操作系统,都需要将代码部分拷贝到RAM中再执行。

再来看一个网上很流行的经典例子:
main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456/0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10); 堆
p2 = (char *)malloc(20); 堆
}
不知道你是否有点明白了,堆和栈的第一个区别就是申请方式不同:栈(英文名称是stack)是系统自动分配空间的,例如我们定义一个 char a;系统会自动在栈上为其开辟空间。而堆(英文名称是heap)则是程序员根据需要自己申请的空间,例如malloc(10);开辟十个字节的空间。由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。而堆上的数据只要程序员不释放空间,就一直可以访问到,不过缺点是一旦忘记释放会造成内存泄露。
网上一个很好的比喻,摘抄下来,以便理解:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
总结:
其实堆栈就是单片机中的一些存储单元,这些存储单元被指定保存一些特殊信息,比如地址(保护断点)和数据(保护现场)。
如果非要给他加几个特点的话那就是:1、这些存储单元中的内容都是程序执行过程中被中断打断时,事故现场的一些相关参数。如果不保存这些参数,单片机执行完中断函数后就无法回到主程序继续执行了。
2、这些存储单元的地址被记在了一个叫做堆栈指针(SP)的地方。
好了,以上就是这些。
上一篇:嵌入式系统的硬件电路该怎样设计
史海拾趣
|
1 政策规范 参照《国务院关于实施国家突发公共事件总体应急预案的决定》(国发[2005]11号)、《“十一五”期间国家突发公共事件应急体系建设规划》(国办发[2006]06号)、《国家应急平台体系建设建设要求》 ...… 查看全部问答> |
|
1月18日最新:71个IC电子通讯岗位,含简单介绍(平均20万以上) 比较急的职位 1.verification,soc verification,上海 2.digital design,做音频,对数字的整个flow要很熟悉,对数模混合模块很熟悉,有降低功耗,减小面积这方面的经验 ,上海 3.pr,后端 2年以上,上海 4.dft,dft 2年左右, ...… 查看全部问答> |
|
我是用的wince6.0,和三星6410的板子,驱动中有两个,一个是USB,另外一个是OTG,USB驱动里面很简单,就只有一个C文件。 当我将系统挂起之后,所有驱动均正常。唤醒之后,大部分驱动正常,在我测试之后,发现: 1. 将OTG驱动去掉, ...… 查看全部问答> |
|
现做一个项目,其中一项功能是用GSM模块向用户发送短信息,但有发时候发出的短信息中调试器中显示是成功了,但对方没有收到,有时候是对方延时30分钟后才能收到。 比如说,我向对方发了N条短信,对方没有立即收到,而是过了很久之后一次性收到N条 ...… 查看全部问答> |
|
我有个跑WINCE的手持机, 开启GPRS模块后,可以浏览网页了 现在我想用这个GPRS 模块收发信息,还要做哪些工作呢? 是否在WINCE系统中,已经提供了相关的函数了? 还是要借助 GPRS模块本身的相关函数接口,才可以收发信息呢??? 谢谢… 查看全部问答> |
|
我这里碰到的一个问题是,不知道如何确定一个dll是否被系统加载了. 我这里自己想的思路就是: 1.打印串口调试信息,信息打印出来了,就表示加载了. 这个方法相对而言比较简单,但是有的时候不太方便. 2.通过USB连接之后,通过进程查看 ...… 查看全部问答> |
|
msp430f149中xin引脚与xout引脚接8M晶振,但是8M晶振不起振 程序是这样的 #include <msp430x14x.h> void main(void){unsigned int i;WDTCTL = WDTPW+WDTHOLD;P5DIR =0X10;P5SEL=0X10;BCSCTL1&= XTS;do{ IFG1 &= ~OFIFG; for ...… 查看全部问答> |




