趣解单片机堆栈概念
- 格式:docx
- 大小:18.27 KB
- 文档页数:6
堆和栈的区别
堆栈的概念⼀直⽐较朦胧,今天做⼀下梳理总结
此处的堆、栈,指的是操作系统中对内存的使⽤⽅式,不同于数据结构中的堆、栈的概念
栈
为执⾏线程留出的内存空间,都在Ram中。
可⽤来存放局部变量,引⽤变量(引⽤在栈⾥,引⽤的内容在堆⾥)。
类似于数据结构的栈,后进先出。
由操作系统分配,分配时⼤⼩就确定了,使⽤完毕⽴即回收。
访问速度快,只使⽤指针移动。
但空间⽐较⼩。
堆
为动态分配留出的内存空间,都在Ram中。
可⽤来存放⼿动new的对象和数组。
不同于数据结构的堆(是⼀个树),内存分配的堆是以链表结构存在的。
操作系统通过调⽤语⾔的运⾏时进⾏分配,初始分配⼀个⼤⼩,在使⽤时可以动态扩展,使⽤完成后若不⼿动释放,不会⽴即释放,要等待垃圾回收时才会释放。
访问速度慢。
若需要分配⼤亮内存时推荐使⽤。
注:数据结构中的堆栈概念
栈:先进后出的数据结构。
堆:⼀棵树。
堆栈是一种数据结构。
一直以为堆栈是一个寄存器,惭愧!教科书定义:所谓堆栈,就是只允许在其一端进行数据插入和数据删除的线性表。
51单片机的单片机的堆栈是在内部RAM中开辟的。
这句话表明了堆栈的位置。
那么堆栈到底有什么作用?堆栈主要是为子程序调用和中断操作而设立的,因此对应有两项功能:保护断点和保护现场。
单片机的程序归根结底是个死循环,反复在执行Main函数(主程序),你可以只写一个函数Main,那么你这个函数随着功能的增多而变得异常大,而且非常不具备可读,这个时候就需要子函数(子程序)了。
主函数在调用完子函数后会返回到主函数中,这样就可以调用其它函数并且继续这个死循环。
在计算机去执行子函数或者中断服务函数,如何确保程序能够正确地返回到主函数中并且继续正确执行后面的内容?因为在执行子函数或者中断服务函数时,很有可能会破坏寄存器单元的内容,但这些寄存器单元在子函数必须要用到?这个问题看起来比较难解决了。
这个时候就要用到断点保护和现场保护了。
保护断点:在调用子程序和堆栈时,将返回地址(执行完子程序或者中断后要执行的下一个指令的的地址(PC 寄存器值)) 送入堆栈,程序返回时,这个值自动弹回PC。
这种方式是自动使用堆栈的,程序中一般无需理会。
在这个过程中,地址送入堆栈时,堆栈指针SP+2,因为51的寻址范围是64KB,再查看RAM中堆栈单元就可以发现这个时候已经变成了PC的值,在返回的时候SP-2,但是堆栈中的内容在下一次堆栈操作之前不会发生变化。
来看下面的仿真图:程序初始化将SP设置为0x07,这个时候RAM中全部被清零。
单步运行。
这个时候SP的值已经变为0x30,但是内容依旧没有改变。
运行到断点。
运行到断点PC的值没什么变化,在执行完Lcall之后,发现RAM中30单元起了变化,0013,PC也+2,而0013就是sjmp st1的地址。
以上是用Protues仿真的结果。
在用KEIL做软仿的时候发现SP会变化,但是对应的内容却没有变化,这个是不是KEIL的一个BUG呢?保护断点是比较简单的,编程者一般不用理会。
堆和栈的区别一、预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
-程序结束后有系统释放4、文字常量区—常量字符串就是放在这里的。
程序结束后由系统释放5、程序代码区—存放函数体的二进制代码。
二、例子程序这是一个前辈写的,非常详细//main.cppint 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);分配得来得10和20字节的区域就在堆区,注意,P1,P2本身在栈区,因为是局部变量。
strcpy(p1,"123456");123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}三、堆和栈的理论知识3.1申请方式stack:由系统自动分配。
例如,声明在函数中一个局部变量int b;系统自动在栈中为b 开辟空间heap:需要程序员自己申请,并指明大小,在c中malloc函数如p1=(char*)malloc(10);在C++中用new运算符如p2=(char*)malloc(10);但是注意p1、p2本身是在栈中的。
一文解析STM32内存管理和堆栈的认知与理解本文主要介绍了STM32内存管理和堆栈的认知与理解,首先介绍的是内存管理的实现原理及分配、释放原理,其次介绍了stm32的存储器结构,最后阐述了堆栈的认知与理解,具体的跟随小编一起来了解一下吧。
STM32内存管理详解内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。
其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。
内存管理的实现方法有很多种,他们其实最终都是要实现2 个函数:malloc 和free;malloc 函数用于内存申请,free 函数用于内存释放。
内存管理的实现原理从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。
内存池被等分为n 块,对应的内存管理表,大小也为n,内存管理表的每一个项对应内存池的一块内存。
内存管理表的项值代表的意义为:当该项值为0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。
比如某项值为10,那么说明包括本项对应的内存块在内,总共分配了10 个内存块给外部的某个指针。
内寸分配方向如图所示到低位地址)即首先从最末端开始找空内存。
当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。
分配原理当指针p 调用malloc 申请内存的时候,先判断p 要分配的内存块数(m),然后从第n 项开始,向下查找,直到找到m 块连续的空内存块(即对应内存管理表项为0),然后将这m 个内存管理表项的值都设置为m(标记被占用),最后,把最后的这个空内存块的地址返回指针p,完成一次分配。
注意,如果当内存不够的时候(找到最后也没找到连续的m 块空闲内存),则返回NULL 给p,表示分配失败。
释放原理。
堆和栈的理解和区别,C语言堆和栈完全攻略在计算机领域,堆栈绝对是一个不容忽视的概念,并且在编写C 语言程序的时候也会频繁用到。
但对大多数C 语言初学者来说,堆栈却是一个很模糊的概念。
“堆栈:一种数据结构,一个在程序运行时用于存放的地方”,相信这可能是很多初学者共同的认识,这也是大部分教科书对“堆栈”的解释。
很显然,用这么简单的概括来解释“堆栈”是不合适的。
要深刻认识堆和栈的概念与区别,还必须从如下两方面说起。
数据结构的堆和栈在数据结构中,栈是一种可以实现“先进后出”(或者称为“后进先出”)的存储结构。
假设给定栈S=(a0,a1,…,a n-1),则称a0为栈底,a n-1为栈顶。
进栈则按照a0,a1,…,a n-1的顺序进行进栈;而出栈的顺序则需要反过来,按照“后存放的先取,先存放的后取”的原则进行,则a n-1先退出栈,然后a n-2才能够退出,最后再退出a0。
在实际编程中,可以通过两种方式来实现:使用数组的形式来实现栈,这种栈也称为静态栈;使用链表的形式来实现栈,这种栈也称为动态栈。
相对于栈的“先进后出”特性,堆则是一种经过排序的树形数据结构,常用来实现优先队列等。
假设有一个集合K={k0,k1,…,k n-1},把它的所有元素按完全二叉树的顺序存放在一个数组中,并且满足:则称这个集合K 为最小堆(或者最大堆)。
由此可见,堆是一种特殊的完全二叉树。
其中,节点是从左到右填满的,并且最后一层的树叶都在最左边(即如果一个节点没有左儿子,那么它一定没有右儿子);每个节点的值都小于(或者都大于)其子节点的值。
内存分配中的堆和栈在C 语言中,内存分配方式不外乎有如下三种形式:1.从静态存储区域分配:它是由编译器自动分配和释放的,即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,直到整个程序运行结束时才被释放,如全局变量与static 变量。
2.在栈上分配:它同样也是由编译器自动分配和释放的,即在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元将被自动释放。
51单片机堆栈深入剖析用C语言进行MCS51系列单片机程序设计是单片机开发和应用的必然趋势。
Keil公司的C51编译器支持经典8051和8051派生产品的版本,通称为Cx51。
应该说,Cx51是C语言在MCS51单片机上的扩展,既有C语言的共性,又有它自己的特点。
本文介绍的是Cx51程序设计时堆栈的计算方法。
1.堆栈的溢出问题。
MCS51系列单片机将堆栈设置在片内RAM中,由于片内RAM资源有限,堆栈区的范围也是有限的。
堆栈区留得太大,会减少其他数据的存放空间,留得太少则很容易溢出。
所谓堆栈溢出,是指在堆栈区已经满了的时候还要进行新的压栈操作,这时只好将压栈的内容存放到非堆栈区的特殊功能寄存器(SFR)中或者堆栈外的数据区中。
特殊功能寄存器的内容影响系统的状态,数据区的内容又很容易被程序修改,这样一来,之后进行出栈操作(如子程序返回)时内容已变样,程序也就乱套了。
因此,堆栈区必须留够,宁可大一些。
要在Cx51程序设计中防止堆栈的溢出,要解决两个问题:第一,精确计算系统分配给用户的堆栈大小,假设是M;第二,精确计算用户需要堆栈的大小,假设是N。
要求M≥N,下面分别分析这两个问题。
2.计算系统分配给用户的堆栈大小Cx51程序设计中,因为动态局部变量是长驻内存中的,实际上相当于局部静态变量,即使在函数调用结束时也不释放空间(这一点不同于标准C语言)。
Cx51编译器按照用户的设置,将所有的变量存放在片内和片外的RAM中。
片内变量分配好空间后,将剩下的空间全部作为堆栈空间,这个空间是最大可能的堆栈空间。
当然,因为Cx51是一种可以访问寄存器的C语言(特殊功能寄存器),因此可在程序中访问SP,将堆栈空间设置得小一点。
不过,一般没有人这么做。
本文只是讨论放在片内RAM的变量。
我们把变量分为两种情况:①用作函数的参数和函数返回值的局部变量。
这种变量尽量在寄存器组中存放。
为了讨论方便,假设统一用寄存器组0,具体的地址为0x00~0x07。
简答题部分1、什么叫堆栈?答:堆栈是在片内RAM中专门开辟出来的一个区域,数据的存取是以"后进先出"的结构方式处理的。
实质上,堆栈就是一个按照"后进先出"原则组织的一段内存区域。
2、进位和溢出?答:两数运算的结果若没有超出字长的表示范围,则由此产生的进位是自然进位;若两数的运算结果超出了字长的表示范围(即结果不合理),则称为溢出。
4、什么是单片机的机器周期、状态周期、振荡周期和指令周期?它们之间是什么关系?答:某条指令的执行周期由若干个机器周期(简称M周期)构成,一个机器周期包含6个状态周期(又称时钟周期,简称S周期),而一个状态周期又包含两个振荡周期(P1和P2,简称P周期)。
也就是说,指令执行周期有长有短,但一个机器周期恒等于6个状态周期或12个振荡周期,即1M=6S=12P。
5、MCS-51单片机通常内部包含哪些主要逻辑功能部件?答:51单片机通常由下列部件组成:一个8位CPU、一个片内振荡器及时钟电路、内部Flash Rom程序存储器、256B的RAM、2个16位的定时/计数器、可寻址64KB片外数据存储器和64KB片外数据存储器和64KB片外程序存储器空间的控制电路、4个8位并行I/O端口及一个可编程全双工串行接口。
6、MCS-51单片机的存储器从物理结构上可划分几个空间?答:MCS-51系列单片机的存储器配置从物理结构上可分为:片内程序存储器、片外程序存储器、片内数据存储器、片外数据存储器。
从逻辑上可分为:片内外统一编址的64KB的程序存储器、片内256B的数据存储器以及片外64KB的数据存储器。
7、存储器中有几个保留特殊功能的单元用做入口地址?分别作什么作用?答:MCS-51系列单片机的存储器中有6个保留特殊功能单元,其中0000H为复位入口、0003H为外部中断0入口、000BH为T0溢出中断入口、0013H为外部中断1入口、001BH 为T1溢出中断入口、0023H为串行接口中断入口。
应用工程的堆与栈一、基本知识C语言因其高效率而成为目前嵌入式微控制器(MCU)编程中使用最多的编程语言,堆栈是C语言区别于汇编语言的最大特点,也是其高效运行的基础。
1、定义1)基本含义事实上,堆栈包括堆(heap)和栈(s tack)两个不同的概念,只是因为其二者都占用MCU的片上RAM空间并对系统内存进行分配和管理,而被习惯性放在一起说。
在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。
可以理解成堆栈是位于MCU片上RAM空间上的一个特殊存储区。
小注:✧堆:队列优先,先进先出(FIFO—first in first out)✧栈,先进后出(FILO—First-In/Last-Out)。
2)详解介绍①堆(heap)是用于动态分配内存的RAM区域,heap的空间是用户手动申请和释放的:C语言中的malloc(size),calloc(num,size)函数分配heap,释放使用free(*heap)函数;②栈(stack)用于分配函数临时变量、在函数调用或中断产生时保存内核CPU 运行时上下文(run time context—包括内核CPU通用寄存器、SP和PC寄存器、状态寄存器(如S12内核的CCR寄存器,存放内核CPU的计算状态)及函数当前的临时变量)以及函数参数传递;其占用的RAM大小与CPU架构(不同的内核CPU其位宽和CPU寄存器数量各不相同)和编译器采用的嵌入式应用程序二进制接口(Embedded Application Binary Interface)有关。
小注:✧栈(Stack)是CPU根据程序运行需求自动分配(也叫push,即压栈)和释放(也称作pop,即出栈)的,无需用户自己维护,但需要在C工程的链接文件中指定其大小。
✧压栈(push):函数调用和中断ISR运行之前,对当前运行函数运行时的上下文进行保护。
✧出栈(pop):函数返回和中断返回时恢复调用函数和中断发生前函数的运行时环境。
大白话解释堆栈-概述说明以及解释1.引言1.1 概述堆栈(Stack)是一种常见的数据结构,被广泛应用于计算机科学中的各个领域。
它是一种“后进先出”(Last In First Out,简称LIFO)的数据结构,类似于我们日常生活中的堆叠物品,即最后放入的物品最先取出。
在计算机科学中,堆栈被用来管理程序运行时的内存。
它按照一定的规则对数据进行存储和操作,使得程序可以高效地执行。
堆栈的基本操作包括“入栈”和“出栈”,即向堆栈中插入数据和从堆栈中取出数据。
入栈操作将数据放入堆栈顶部,出栈操作则从堆栈顶部删除数据。
堆栈的特点之一是其操作快速高效。
由于堆栈是一个有限空间,存储和访问数据的代价相对较低,使得程序可以快速地执行堆栈操作。
此外,堆栈还具有良好的封装性,即不允许直接访问中间的数据项,只能通过栈顶进行操作。
这种封装性使得程序更安全,减少了错误的发生。
堆栈在计算机科学中有着广泛的应用场景。
在程序中,堆栈常被用于存储函数调用、表达式求值等临时数据。
此外,堆栈还可以用来实现算法中的回溯和递归操作,以及处理系统中的进程调度等任务。
堆栈的应用不仅限于软件领域,在硬件领域也有广泛的应用,例如处理器中的指令堆栈、网络中的数据包堆栈等。
通过对堆栈的深入理解和掌握,我们可以更好地设计和优化程序,提高系统的效率和性能。
因此,了解堆栈的定义、特点和应用场景非常重要。
接下来的章节将详细介绍堆栈的定义和特点,以及它在不同领域中的应用和优势。
通过对堆栈的全面了解,我们可以更好地利用它来解决实际问题,并为未来的发展展望提供指导。
1.2文章结构文章结构部分的内容可以按照以下方式编写:文章结构部分是整篇文章的重要组成部分,它帮助读者更好地理解文章的脉络和逻辑结构。
本文将通过引言、正文和结论三个部分来组织讲解。
首先,引言部分将为读者提供一个概述,简要介绍将要讨论的主题——堆栈。
文章结构的目的是让读者对即将讲解的内容有一个整体的把握。
堆和栈有什么区别看完不再混淆在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构。
堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。
在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。
要点:堆,队列优先,先进先出(FIFO—first in first out)[1] 。
栈,先进后出(FILO—First-In/Last-Out)。
对于编程初学者来说会接触到一些难以理解的名称,比如堆(heap)、栈(stack)、堆栈(stack)等。
初学开发过程中往往让人混淆不清。
本篇文章就是为他们所写的,关于堆和栈的具体区别,来帮助初学者理清思路,看完不再混淆。
堆和栈的区别一直都是永恒的话题,为此我也查了很多的资料,以防自己的理解错误,而给他人造成理解偏差。
先从最简单的一个例子引出堆和栈:void function(){int *p = (int *)malloc(10*sizeof(int));}这是C语言开发学习过程中,必不可免要学习的知识,动态分配一块空间,空间在堆区大小是40字节(32位系统中)。
而定义的指针变量p是局部变量(在栈区中占用4字节空间),用来存放刚刚前面动态分配的空间的首地址。
可以看出,在这一句代码中同时包含了栈和堆,如图1所示。
我们从以下几个方面比较一下堆和栈:(1)存储内容不同栈:在函数调用时,栈中存放的是函数中(最底下是函数调用后的下一条指令)各个参数(局部变量)。
堆:一般是在堆的头部用一个字节存放堆的大小。
堆中的具体内容有程序员安排。
(2)管理方式上不同栈:由系统自动分配空间,同时系统自动释放空间。
例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间,当对应的生存周期结束后栈空间自动释放。
堆:需要程序员手动申请并且手动释放,并指明大小,在C语言中malloc函数申请,释放free函数,在C++中 new和delete实现。
一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc大家好,我是无际。
有一周没水文了,俗话说夜路走多了难免遇到鬼。
最近就被一个热心网友喷了。
说我的文章没啥营养,所以今天来一篇烧脑的。
哈哈,开个玩笑,不要脸就没人能把我绑架。
主要是最近研发第二代物联网网关项目,必须要用到一个功能:内存管理。
温馨提醒,全文4700多字,其中技术点是你进阶到高手必须要学习的,最好收藏,反复专注地看,否则可能会感觉在看天书。
说到内存管理大家会可能想到malloc和free函数。
在讲这两个函数之前,我们先来讲讲栈(stack)和堆(heap)的概念。
1.栈(stack)我们单片机一般有个启动文件,拿STM32F103来举例。
这个Stack_Size就是栈大小,0x00000400就是代表有1K (0x400/1024)的大小。
那这个栈到底用来干嘛的呢?比如说我们函数的形参、以及函数里定义的局部变量就是存储在栈里,所以我们在函数的局部变量、数组这些不能超过1K(含嵌套的函数),否则程序就会崩溃进入hardfaul。
除了这些局部变量以外,还有一些实时操作系统的现场保护、返回地址都是存储在栈里面。
还有一点题外话,就是栈的增长方向是从高地址到低地址的,这个用得不多,暂时不需要去深究。
2. 堆(heap)malloc()函数动态分配的内存就属于堆的空间。
同样,在单片机启动文件里也有对堆大小的定义。
0x00000200就是代表有512个字节。
这意味着如果你用malloc()函数,那么最大分配的内存不能大于512字节,否则程序会崩溃。
网上很多文章说,全局变量和静态变量是放在堆区。
但是我做了实验,把堆的空间大小设置成0,程序正常运行并无影响。
这说明我们平时定义的全局变量、静态变量是不存放在堆的,而是堆栈以外的另外一篇静态空间区域,个人理解,如果有误请指正。
Ok,那么我们简单了解了堆和栈的概念,也知道malloc()函数分配的是堆的空间。
计算机中堆栈的概念这两天学习win32的API,了解到了计算机中堆栈的概念,相信很多程序员有时候也弄不明⽩计算机中的堆栈的。
再次为堆栈做⼀下详细解析。
在英⽂中,我们管栈称为stack,管堆称为heap。
在计算机中,堆栈是两种不同的数据结构,但堆栈均为⼀种按序排列的数据结构。
只能在⼀端对数据项进⾏插⼊和删除。
其中的关键是,堆,的排列顺序是随意的,⽽栈,排列顺序是先进后出(First In Last Out)。
堆:为编译器⾃动的分配与释放,⽤来存放函数的参数值与局部变量。
其操作⽅式类似于数据结构中的栈。
栈使⽤的是⼀级缓存,通常都是在调⽤时候存储于存储空间中,在⽤完后由编译器⾃动的释放。
堆:为编程⼈员分配与释放,如果在程序结束的时候没有释放,⼀般会被OS所回收,分配⽅式类似于链表。
堆⼀般存储于⼆级缓存。
数据结构,堆可以被看成⼀棵树。
栈则是⼀种先进后出的数据结构。
在具体介绍之前,我们应该介绍⼀下在C或者C++语⾔中变量的存储区域。
1,栈区(stack):这块区域由编译器分配与释放内存空间,⼀般存储函数的参数值与局部变量值。
类似于数据结构中的栈。
2,堆区(heap):这块区域由程序员⾃⼰分配与释放,其余数据结构中的堆是两码事,分配⽅式类似于链表。
3,全局区(静态变量区):这块存储区域⽤于存储全局变量(global)和静态变量(static),初始化的全局变量和静态变量存储于⼀块区域,未初始化的全局变量和静态变量存储于另⼀块区域。
程序结束后系统⾃动释放。
4,⽂字常量区(静态缓冲区):这块区域⽤于存储常量静态字符串,在前⾯⽂章我有提到过并且演⽰过,⽤于存放const char*类型的变量。
在程序运⾏中,是不可能对其进⾏修改的,如果修改的话,程序将会报错并且crush,程序结束后由系统⾃动释放。
5,程序代码区:该区域⽤于存放函数体的⼆进制代码。
下⾯,我⽤⼀段程序来解释在什么地⽅存放各种变量。
上⾯的例⼦完全诠释了各种变量存储的地⽅在程序中。
堆栈是计算机系统中的一个重要概念,也是理解微型计算机组成的一个基础概念。
堆栈是一种存储部件,即数据的写入跟读出不需要提供地址,而是根据写入的顺序决定读出的顺序。
堆栈也是一种数据结构。
有一个地址指针总指向最后一个压入堆栈的数据所在的数据单元,存放这个地址指针的寄存器就叫做堆栈指示器。
数据一个一个地存入,这个过程叫做“压栈”。
在压栈的过程中,每有一个数据压入堆栈,就放在和前一个单元相连的后面一个单元中,堆栈指示器中的地址自动加1。
读取这些数据时,按照堆栈指示器中的地址读取数据,堆栈指示器中的地址数自动减1。
这个过程叫做“出栈pop”。
如此就实现了后进先出的原则。
一般的堆栈存储器由RAM、寄存器A,寄存器B构成。
算术运算一般在寄存器A和寄存器B 之间进行,其中的数据可能来自于进栈的输入也可能来自栈堆的出栈。
运算结果则会放入寄存器B中以待下步操作。
此次的课程设计做出的堆栈处理器,使其能与外部数据总线进行数据交换,且符合堆栈要求(先进后出),并能对存储的数据进行算术运算,且存储的数据的数据位不少于8位,通过数码管显示操作数据及运算结果(只有寄存器A、B 直接与外部总线进行数据交换,RAM只和寄存器B进行数据交换)。
关键词:堆栈,RAM, PUSH, POP , 寄存器A,寄存器B一. 任务解析 (3)二. 系统方案论证 (3)2.1总体方案与比较论证 (3)2.2 设计思路 (4)2.3系统原理与结构 (4)2.3.1 系统框图 (4)2.3.2 系统结构框图 (5)2.3.3堆栈电路图 (5)三. 设计过程 (6)3.1堆栈存储器的设计 (6)3.1.1堆栈存储器设计原理及仿真结果 (6)3.2对数据进行算术运算的设计及仿真 (7)3.2.1 对存储器中数据进行加法运算 (7)3.2.2 对存储器中数据进行减法运算 (8)3.2.3 对存储器中数据进行乘法运算 (8)3.2.4 对存储器中数据进行除法运算 (9)四. 总结 (9)4.1遇到的问题及解决方案 (9)4.2设计心得 (10)4.3参考文献 (10)一、任务解析堆栈处理器应能完成两个基本的功能:与外部数据线的数据交换符合堆栈要求(先进后出);对存储的数据能进行算术运算。
一个故事看懂单片机中的堆栈(完整版)因为单片机有CPU、存储器、IO等等,使他(人性化一点以配合下文)看起来就像一个比较小的计算机,所以,在理解单片机的时候如果能把你之前有的那些也许仅仅是直觉上的对计算机的理解融入进来的话,可能会对你学习单片机的概念有极大的帮助,至少对于我是这样的。
我想在关于单片机的众多让你头晕脑胀、摸不着头脑甚至想撞墙的概念里面,“堆栈”可能是其中最可恶的一个,因为即使单单是从汉语的角度来理解这个词就已经让你很晕了,其实我最初也想不通这是哪位大侠的创意,不过不用担心,这里我们完全不去讨论关于这个词的问题(这个词用得其实很好“堆”和“栈”都有他们各自的意思,准确的概括了这个区域的功能,有兴趣可以Baidu一下),这里我会打一个比较有趣的比方,以此来绕过那些令你想撞墙的概念,并使你在直觉上对“堆栈”这个概念有一个深刻的理解。
你基本上应该清楚,单片机里面是有存储区和CPU的,如果你不清楚,那么我刚刚告诉你了,请记住。
现在,请你把单片中的CPU想成一个人(你完全可以把他想成是你宿舍的那个天天和你吵嘴的同学,一会你就会发现这会非常有趣),在这里就叫他C哥吧,不过这个人不同于常人,有一些特点,一会我们会慢慢说清楚,现在要告诉你的关于这个人的第一个特点是:他的记忆能力很差。
下面,请你把存储区想象成一个一个排好的小盒子,这些盒子的作用大致可以分成两类:1、保存写有你命令的纸条,比如你在某个盒子里面的纸条上写着:去洗我的袜子!;2、保存你的一些东西,比如你那双正在污染宿舍空气的臭袜子。
因为C哥是一个记忆力不怎么好的人,所以,这些盒子都有自己的编号,以方便他查找。
那么,现在,我们可以来说明一下单片机是如何工作的了。
首先,你要把所有的命令还有需要处理的东西放进那些小盒子,比如刚才提到的你那双待洗的袜子还有那张纸条,这时你应该发现C哥另一个特点:笨——他只会做你明确告诉他的事情,也就是说,如果你没有在纸条上写“去洗我的袜子!”,那么C哥极有可能会无动于衷地看着你的袜子直到他被熏晕倒,当然,更可能的情况是他根本找不到你的袜子…好了,当你把要做的事情和该怎么做写到盒子里之后,下面的任务就交给C哥了。
堆(heap)和栈(stack)有什么区别??堆栈其实是两种数据结构。
堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。
要点:堆:顺序随意栈:后进先出(Last-In/First-Out)简单的可以理解为:heap:是由malloc之类函数分配的空间所在地。
地址是由低向高增长的。
stack:是自动分配变量,以及函数调用的时候所使用的一些空间。
地址是由高向低减少的。
预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。
其操作方式类似于数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
- 程序结束后有系统释放4、文字常量区—常量字符串就是放在这里的。
程序结束后由系统释放5、程序代码区—存放函数体的二进制代码。
二、例子程序这是一个前辈写的,非常详细//main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main(){int b; 栈char s[] = "abc"; 栈char *p2; 栈char *p3 = "123456"; 123456在常量区,p3在栈上。
static int c =0;全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
c语言中的堆栈摘要:1.堆栈的概念与作用2.C语言中的堆栈实现3.堆栈的应用场景4.堆栈的操作实例5.堆栈溢出的处理方法正文:堆栈是计算机科学中一种重要的数据结构,它是一种后进先出(Last In First Out,LIFO)的数据管理方式。
在C语言中,堆栈为开发者提供了一种方便的组织和管理数据的方式,尤其在函数调用、局部变量管理和程序控制流方面具有很高的实用价值。
1.堆栈的概念与作用堆栈是一种线性数据结构,由一系列元素组成。
栈顶和栈底是堆栈的两个重要概念。
栈顶指当前最新添加的元素所在的位置,而栈底则是最早添加的元素所在的位置。
堆栈的主要作用有以下几点:- 函数调用:C语言中,函数调用是通过堆栈来实现的。
每当一个函数被调用,它的局部变量、返回地址和参数等数据会按照特定的顺序压入堆栈。
函数执行完毕后,堆栈会按照相反的顺序弹出这些数据,从而实现函数的返回。
- 局部变量管理:在C语言中,局部变量的生命周期和作用域受到堆栈帧的控制。
每当创建一个局部变量,堆栈会为其分配一块内存空间,并在函数调用时自动弹出该变量。
- 程序控制流:堆栈还可以用于实现条件分支、循环等控制结构。
例如,在嵌套循环中,循环计数器和其他相关数据可以通过堆栈进行管理。
2.C语言中的堆栈实现C语言标准库提供了堆栈操作的函数,如`malloc`、`calloc`、`realloc`和`free`等。
这些函数在操作系统层面通过内存管理单元(MMU)实现,为开发者提供方便的堆栈操作功能。
3.堆栈的应用场景堆栈在编程中的应用场景非常广泛,以下列举了一些典型的应用:- 函数调用:如前所述,C语言中的函数调用是通过堆栈实现的。
- 数据结构:堆栈可以用于实现各种数据结构,如链表、树、图等。
- 算法优化:堆栈在算法优化中具有很高的价值,如栈式数据结构、回溯算法、深度优先搜索等。
- 内存管理:堆栈内存管理是C语言程序运行的基础,通过堆栈分配和释放内存,实现程序的动态内存分配。
关于单片机堆栈概念的一个有趣的解释
因为单片机有CPU、存储器、IO等等,使他(人性化一点以配合下文)看起来就像一个比较小的计算机,所以,在理解单片机的时候如果能把你之前有的那些也许仅仅是直觉上的对计算机的理解融入进来的话,可能会对你学习单片机的概念有极大的帮助,至少对于我是这样的。
我想在关于单片机的众多让你头晕脑胀、摸不着头脑甚至想撞墙的概念里面,“堆栈”可能是其中最可恶的一个,因为即使单单是从汉语的角度来理解这个词就已经让你很晕了,其实我最初也想不通这是哪位大侠的创意,不过不用担心,这里我们完全不去讨论关于这个词的问题(这个词用得其实很好“堆”和“栈”都有他们各自的意思,准确的概括了这个区域的功能,有兴趣可以Baidu一下),这里我会打一个比较有趣的比方,以此来绕过那些令你想撞墙的概念,并使你在直觉上对“堆栈”这个概念有一个深刻的理解。
你基本上应该清楚,单片机里面是有存储区和CPU的,如果你不清楚,那么我刚刚告诉你了,请记住。
现在,请你把单片中的CPU想成一个人(你完全可以把他想成是你宿舍的那个天天和你吵嘴的同学,一会你就会发现这会非常有趣),在这里就叫他C哥吧,不过这个人不同于常人,有一些特点,一会我们会慢慢说清楚,现在要告诉你的关于这个人的第一个特点
是:他的记忆能力很差。
下面,请你把存储区想象成一个一个排好的小盒子,这些盒子的作用大致可以分成两类:1、保存
写有你命令的纸条,比如你在某个盒子里面的纸条上写着:去洗我的袜子!;2、保存你的一些东西,比如你那双正在污染宿舍空气的臭袜子。
因为C哥是一个记忆力不怎么好的人,所以,这些盒子都有自己的编号,以方便他查找。
那么,现在,我们可以来说明一下单片机是如何工作的了。
首先,你要把所有的命令还有需要处理的东西放进那些小盒子,比如刚才提到的你那双待洗的袜子还有那张纸条,这时你应该发现C哥另一个特点:笨——他只会做你明确告诉他的事情,也就是说,如果你没有在纸条上写“去洗我的袜子!”,那么C 哥极有可能会无动于衷地看着你的袜子直到他被熏晕倒,当然,更可能的情况是他根本找不到你的袜子…好了,当你把要做的事情和该怎么做写到盒子里之后,下面的任务就交给C哥了。
C哥做事真的很讲原则,他会按照你给定的顺序或者——如果你没有给定的话,根据盒子上面的编号按照从小到大的顺序——一个一个地打开盒子,读取里面的命令、处理相应的事件,直到所有的事情都执行完毕,他就会休息。
请你牢记这个简单而有趣的过程,因为其实单片机就是这样工作的,当然,这里忽略了许多细节,但是这对你从直觉上理解单片机的概念以及足够了。
下面,就要开始说明堆栈这个概念了,思来想去,还是觉
得如果直接把“堆栈”这个词用到文中来,实在不符合本文的风格,考虑到其实“堆栈”也是存贮区(这一点你要记住,堆栈并不是一个像专用寄存器那样专门的一个区域,它是由你在通用RAM区指定的。
),按照本文的说法也就是一些盒子,所以,现在我们把“堆栈”改名叫“记忆盒子”,你可以感觉到,“堆栈”的作用和记忆有极大的关系,不过你也不用在这里纠结这个名字的由来,下面我会说的。
现在,请注意,我要开始解释“记忆盒子”了,也就是“堆栈”。
大致上说,“记忆盒子”的作用是当C哥执行某任务到一半的时候突然有了更紧急的是事情要执行的时候用来保存当前任务的(包括盒子的编号和盒子里面的东西)。
这么说你肯定晕了,其实,通俗一点,就是当C哥洗袜子洗到一半的时候突然接到你的命令要去打开另一个盒子(那个盒子里的纸条上可能写着“给我换尿布”)并执行里面的命令,因为C哥记忆力很差,以至于他做完那件紧急的事情后记不起要回到哪个盒子来继续执行“洗袜子”这个命令,这时候,他要把现在手头的东西保存到“记忆盒子”里,要保存的东西有:1、放着纸条和袜子的盒子的编号(注意这里其实是两项内容);2、那双袜子。
这样,当他执行完紧急任务后会去记忆盒子里,从里面找到两张纸条,和一双袜子(这个时候C哥还是没有想起来他要洗袜子,他必须要到那张写着洗袜子命令的纸条),他按照两张纸条的信息知道自己要去哪个盒子去洗袜子,并在那里继
续完成洗袜子的任务。
你可能会发现,在这一段的解释里面有一个重要的漏洞,那就是在C哥执行完紧急任务后他是如何知道储存着原来的任务信息的盒子的编号是存储在哪个“记忆盒子”里呢?别着急,下面我会解释的。
从本质来说,“记忆盒子”与普通的盒子是没有区别的,他们都是单片机里面的存储单元,证明这一点的最好证据就是堆栈是需要你来指定的,也就是说,你要预先把一些盒子指定为“记忆盒子”。
下面,说明一下是如何指定“记忆盒子”的。
其实这个过程很简单,在单片机的专用寄存器里面有一个SP 指针(81H),这个指针里面记录着堆栈的开始处的地址。
用符合本文的话来解释就是,C哥的衣服上有一个口袋(也就是SP 指针),这个口袋里面的“神奇纸条”上记录着第一个“记忆盒子”的编号,而指定“记忆盒子”的过程就是你在这张“神奇纸条”上写上一个盒子的编号(作为第一个“记忆盒子”的编号),这个纸条会自动地将纸条上的编号加1或者减1,所以,某个目前并不确定的区域内盒子具备了成为“记忆盒子”的可能,注意,堆栈的大小是不能规定的,这就是为什么用“生长”这个词来形容堆栈。
现在,关于堆栈的概念基本上都介绍完了,但是,我知道,你可能还是很晕,甚至比看之前还晕,那是因为刚才叙述的这个过程是分开的,而且逻辑上并不是顺序的,下面,顺序的说一下,相信你马上就明白了。
主角仍然是傻傻笨笨但任劳任怨的C哥,他一个一个的打开盒子按照里面的纸条上的说明执行你规定的任务。
而你,为了防止他在执行复杂任务时犯傻,把一个盒子指定为“记忆盒子”,并把这个“记忆盒子”的位置写在了一张“神奇纸条”上放在了C哥的口袋里。
现在,C哥正在洗你的袜子,这个时候,他突然接到你的命令要去给你换尿布,而C哥知道自己很笨,所以他自动地掏出了口袋里的纸条,找到了第一个“记忆盒子”,然后拿出一张空白纸条,把装着“给我洗袜子”那张纸条的盒子的编号写在了上面并放进“记忆盒子”。
然后,他把“神奇纸条”放回了口袋里。
当这个任务完成后“神奇纸条”会自动将写在它上面的编号加1,也就是将一个新的、空的“记忆盒子”的编号写在上面。
之后,他会按照刚才的过程把装着袜子的那个盒子的编号以及袜子本身分别放进不同的记忆盒
子(现在已经有三个盒子成为“记忆盒子”,堆栈已经长大了,红色下划线的字体就是这三个盒子里的内容,注意是有先后顺序的)。
再然后,他就去给你换尿布了…
现在,尿布换完了,不过,果不其然,C哥完全忘记了他要给你洗袜子这件事情了,不过,他记得一件事,那就是看口袋里的纸条。
于是,他摸出了口袋里的纸条,上面当然是一个“记忆盒子”的编号,他按照编号找到了第一个“记忆盒子”(按照上一段的顺序应该是第三个“记忆盒子”),里面应该是一双你的袜子,于是他拿到了你的袜子。
但是,他还是不知道
该干什么,于是他再次摸出了“神奇纸条”,这时,纸条上的编号已经自动减1了,于是,他找到了新的“记忆盒子”,里面的纸条上记录着袜子本来放置的盒子的编号,于是,他把袜子放到了那个盒子里。
恩,你可以想到,现在C哥还是不知道要对袜子做些什么,他耐心的又一次摸出了那张“神奇纸条”,这次按照上面的编号,他找到了一张纸条,上面写着的仍然是一个盒子的编号。
C哥按照编号找到了那个盒子,发现那个盒子里的纸条上写着“给我洗袜子!”…至此,C哥又回到了原来的任务——洗袜子。
现在,我希望你已经明白了,堆栈其实就是你指定的一个些存储单元,这些存储单元被指定只用来保存一些特殊信息,比如地址(保护断点)或者一些数据(保护现场),如果你一定要说这个存储区有什么特别的话,那就是:1、这些存储单元内的内容都是CPU在执行某任务中途被打断时的一些相关参数;2、这些存储单元的地址被记在了一个叫堆栈指针的地方,也就是C哥口袋里的那张纸条上!。