当前位置:首页 > 单片机 > 单片机
[导读]栈是一种具有先入后出特性的数据结构,前面说过,这种特性常常用来帮住我们“原理返回”或者“保持原样”。试想,当我们第一次来到一个陌生的城市,走在陌生的街道上,寻找一个陌生的目标,最令

栈是一种具有先入后出特性的数据结构,前面说过,这种特性常常用来帮住我们“原理返回”或者“保持原样”。试想,当我们第一次来到一个陌生的城市,走在陌生的街道上,寻找一个陌生的目标,最令我们有安全感的莫过于仔细记录走过的每一个街道、穿过的每一个路口--这种安全感来源于潜意识里“万一找不到目的地就原路返回”的想法。记得20世纪90年代,有一首家喻户晓的流行歌曲《星星点灯》中曾这样唱到“星星点灯...为迷失的孩子,照亮来时的路”。


“找到来时的路”这种想法是人们基本的求生本能,对有人类编写的C语言编译器来说,也是这样--面对一层一层复杂嵌套关系的函数调用,编译器总是试图记录下我们调用的过程,以便“找回回去的路”。栈就在这种场合中,得到了广泛的应用。


C语言支持函数的调用,这完全得益于栈式分配策略的使用。所谓栈式分配,抛去复杂的技术细节,简单说来,就是将函数内部使用的种种信息(例如,局部变量)在发生函数嵌套调用时,压入栈中“记录下所走过的路”。这样,当调用的函数运行结束需要返回时,编译器就能很容易从栈中找到“来时的路”。使用模拟的方法,我们来具体看看这一过程。


我们假设:一个函数中所有牵涉到的局部信息都被包含在一个与函数同名的接节点中。当我们在某一个函数中发生了对另外一个函数的调用,就将本函数的局部信息压入栈中--也就是将以该函数命名的结点压入栈中:当我们从某一函数中返回,就从栈中弹出一个结点。观察一段代码的函数调用情况,了解编译器如何借助来实现函数的嵌套调用。


//这是一段演示用的伪代码,包含了一些函数并设置了一些断点便于观察

//函数的细节已经省略,只保留了对其他函数的调用关系

//函数A

void FuncA(void)

{

//没有任何针对其他函数的嵌套调用

/*断点A1*/

}

//函数B

void FuncB(void)

{

...

FuncA();//调用了函数A

/*断点B1*/

...

}

//函数C

void FuncC(void)

{

...

FuncB();//调用了函数B

/*断点C1*/

FuncA();//调用了函数A

/*断点C2*/

...

}

//主函数

void main(void)

{

...

/*在这里,我们设置一个程序断点,称为断点1*/

FuncA();

/*断点2*/

FuncB();

/*断点3*/

FuncC()

/*断点4*/

...

}

当程序运行到断点1时,因为还没有发生任何函数调用(我们假设测试环境中没有使用到操作系统,因此不存在操作系统调用main函数的问题,也就是不存在将操作系统相关的内容压入栈中的问题),此时,栈是空的,如图13-10(a)所示。


程序继续运行,发生函数调用--FuncA(),并在其中遇到了断点A1。因为此时发生了函数的调用,结点main被压入栈中。此时只是一个结点,如图13-10(b)所示。程序运行到断点2,系统从函数FuncA()返回,因此,将结点main弹出,如图13-10(c)所示。


继续运行程序,直到再次遇到断点A1。此时,栈中有两个元素,从栈顶向下分别是FuncB、main。这说明,在此之前,发生了两次调用:首先是main调用了FuncB,紧接着在FuncB中调用了FuncA,如图13-11(a)所示。当我们遇到断点B1时,程序已经从FuncA中返回,因此弹出了栈顶元素FuncA,如图13-11(b)所示。经过断点3时,结点main也被弹出,栈再次成为空栈,如图13-11(c)所示。


当程序第三次执行到断点A1时,由于发生了三次函数调用,因此,栈中有三个结点FuncB,FuncA和main,如图13-11(d)所示。再次经过断点B1时,程序从函数FuncA中返回,因此弹出了栈顶元素FuncB,如图13-11(e)所示。程序继续执行,从函数FuncB中返回遇到断点C1时,结点FuncC被弹出,如图13-11(f)所示。


从断点C1向后执行,调用函数FuncA第四次遇到断点A1,结点FuncA再次被压入栈中,如图13-12(a)所示。程序从函数FuncA返回,经过断点C2 时,弹出栈顶指针FuncA,如图13-12(b)所示。当我们遇到断点4时,程序已经回归到主函数main(),栈中最后一个结点被弹出,称为空栈,如图13-12(c)所示。


通过上面的模拟,我们展示了C编译器利用栈实现函数嵌套条用的原理。详细情形大家可以参考编译原理的相关内容,这里就不再深入。前面,我们知道,没当发生一次函数调用,编译器都要保存当前的相关信息。这一信息至少包括两大部分:其一,用于描述程序从函数调用中返回时,返回到哪个函数位置;另一部分,用于描述与当前函数有关的一些局部信息(比方说局部变量)。在ICC中,编译器将两个独立开来,分别使用两个栈来保存。保存函数返回地址(也就是第一部分)的栈被称为硬件栈(Hardware Stack 或者 Resturn Stack)。保存当前函数局部相关信息的栈,我们称之为软件堆栈(Software Stack)。


将原来完整的结点信息一分为二,究竟是出于怎样的考虑呢?我们知道,单片机的内存容量有限(ATMeag48的SRAM仅有512个字节),不可能允许无限制的函数嵌套,必须对栈的尺寸加以限定。在正常情况下,一个结点中包含的信息总是包含定长和不定长两个部分。其中,表示函数返回地址的部分由于指针长度固定为2个字节,因此属于定长部分。将其单独作为一个结点保存在硬件堆栈中,便于规定函数允许嵌套的最大深度(例如,当我们设定HW Stack的最大尺寸是16时,就表示所允许的函数嵌套深度最大为8层)。出去函数返回地址,我们将其余的变长信息统一放在软件堆栈中,而这一部分的尺寸我们是无法预计的--栈究竟需要多大空间,完全取决于用户在函数中定义了多少局部信息(比方说局部变量)及函数嵌套了多少层,因此,我们总希望能给HW Stack提供尽可能大的空间。


出于以上考虑,ICC系统采用硬件栈和软件栈分开存储的方式。编译器要求硬件栈的大小必须在程序编译器前由用户给定(在ICC集成开发环境中,有Compile Option--Target选项卡的Return Stack Size选项卡来设定),如图13-13所示。硬件栈位于SRAM的高地址,采用向上生长的方式,大小直接受到从栈底地址开始至存储器顶端所剩余的空间限制。这一空间大小恰好等于Return Stack所设置的数值。软件栈与硬件栈背靠背存放,采取向下生长的方式,虽然其大小受到诸多因素的共同影响,但最大尺寸在编译完成后也是确定的,如图13-14所示。


考虑到存储器的大小的限制,我们在编写单片机的程序时,一定要精打细算。一个程序,当系统中使用了大量的中断资源,并且允许了中断嵌套的存在,那么在极端的情况下,中断处理程序就很容易发生嵌套现象。此时适当扩大硬件堆栈的大小,支持较大的函数嵌套深度,往往能解决很多莫名其妙的跑飞问题。与拥有丰富存储器资源时的状况不同,由于局部变量在函数发生嵌套时,都要占用软件堆栈空间,因此大量使用使用局部变量或者使用了占用空间颇为可观的局部数组(也包括体积巨大的结构体),在嵌套深度较大时,都有可能造成向下生长的软件堆栈侵入其他存储区域(详细情形阅读ICC的帮助文档),导致某些变量意外修改、程序跑飞等现象。解决这一问题的方法其实很简单,在某些局部变量占用空间较大的情况下,将其通过关键static声明为静态变量--这样即保证了变量的局限性,又避免了将这些内容压入软件栈中(静态局部变量在存储时和全局变量没有本质区别,采用的都是 静态分配),只不过每次使用这些变量之前都要记得补充必要的初始化代码。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

杭州2024年5月20日 /美通社/ -- 5月20日,百世供应链旗下百世云仓在2024年全国网络大会上,宣布了其全面出海战略。聚焦于东南亚市场的新机遇,并积极推动品牌走向国际市场。 百世供应链召开2024年百世云仓全...

关键字: 供应链 网络 触点 软件

5月16日,2024世界电信和信息社会日大会在浙江宁波召开,在第55个世界电信日即将来临之际,共同探讨以推动数字创新赋能新型工业化之路。OPPO作为AI终端厂商代表,受邀出席AI终端未来之路分论坛。OPPO AI技术战略...

关键字: AI 端云协同 大模型

国际货币基金组织(IMF)总裁克里斯塔利娜・格奥尔基耶娃(Kristalina Georgieva)日前表示,AI正在像“海啸”一样冲击着全球劳动力市场。

关键字: IMF AI 劳动力市场 GPT-4o

西门子 Xcelerator as a Service 解决方案将登录微软 Azure,以应对不断增长的客户需求。西门子的 Teamcenter X 产品生命周期管理软件将作为首个登录 Azure 的软件

关键字: AI 自然语言处理

引领供应链数字化转型新潮流 上海2024年5月16日 /美通社/ -- 5月14日,"第七届亚太智慧供应链与物流创新博览会"在上海顺利举办,作为中国和亚太区最大规模,最有影响力的顶流供应链物流盛会,...

关键字: 数字化 软件 供应链管理 控制

最新消息,多位内部人士昨天透露:微软总部下发邮件,通知中国区负责 AI 研究的多个团队整体从中国搬离,涉及员工或达数百人。

关键字: 微软 AI

上海2024年5月13日 /美通社/ -- 在数字化时代,高效的税务管理和ERP系统成为企业发展的关键。为了满足这一需求商应信息科技与Exact Software 易科软件就金四全电票税系统与ERP系统集成及商务合作建立...

关键字: AC 软件 BSP 数字化

北京2024年5月13日 /美通社/ -- 5月10-11日,"EPAI种子计划"正式启航!首期"基于EPAI的大模型应用实践研讨会"在北京智谷大厦成功举行。浪潮信息携手二十家元脑...

关键字: 开发平台 模型 AI 研讨会

北京2024年5月13日 /美通社/ -- 5月11日,鲲鹏昇腾开发者大会2024期间,华为举办"昇思AI框架及大模型技术论坛",软通动力数字基础设施与集成事业部总经理谢睿受邀出席、软通动力...

关键字: AI 模型 BSP 精度

上海2024年5月13日 /美通社/ -- CONNECT 2 是更加用户友好的声卡,仅需轻点几下,它就能为人声和乐器的录制增添异彩。触控面板触感舒适、控制精准、一目了然。所有输入输出信号均可独立静音。自动设置功能通过内...

关键字: NEC 声卡 控制 软件
关闭
关闭