微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51堆栈的安全(精确)设置

51堆栈的安全(精确)设置

时间:11-28 来源:互联网 点击:
几个问题:
1、编译器、连接器把堆栈段定位在IDATA内所有段的最后面,也即内存IDATA高端;
2、中断堆栈被定位在堆栈段内的最后面,即IDATA最顶端;所以堆栈段的安全余量设置,实际上是中断堆栈深度的配置。
3、如果不考虑系统堆栈的安全余量设置,一个没有二级中断嵌套的一级中断堆栈深度应该是13字节。——为什么?
4、系统中断的安全余量配置应该是……字节。——为什么?

下面详细说明:

1、整个51内存256字节。C51首先分配全局静态变量在IDATA低端,接着分配的是项目中所有函数的参数和局部变量共享覆盖区——也属于全局静态变量区(段)。(有没有动态数组区段冷漠不知道也不关心,)然后就是系统堆栈段,其栈底指针?STACK——由C51自动生成,栈顶应该是IDATA顶端——0xFF。系统堆栈深度=0xFF-(?STACK)。
如果项目中含有汇编模块, 那么系统堆栈?STACK中还包含汇编模块私有堆栈STACK(指针指向)如果项目中包含有reentrant 重入函数 foo,那么系统堆栈中还包含有每个foo所属的私有模拟堆栈simulatedstack;它也是C51为每个reentrant 函数自动分配的。对于interrupt 属性函数,C51为其分配中断函数私有堆栈……还有硬件堆栈hardwarestack 的概念(函数调用CALL或者中断发生时由硬件自动压入PC的堆栈。)
所以,一个系统堆栈段内分配了很多私有堆栈,所谓私有,应该是操作系统概念,用在这里是为了与系统堆栈?STACK 区分概念,例如,当一个中断事件发生时,它所打断的后台程序F1 所正在使用的堆栈,是不可能与中断函数堆栈共享的。——2者堆栈都是私有的。
由于中断函数具有最高优先权,且堆栈独立,所以我说中断函数堆栈必然处在所有其它私有STACK之上,是IDATA最顶端的堆栈;——安全余量必是在中断堆栈之上分配。

……Cx51编译器会(自动——冷漠注释)产生一个?STACK的堆栈段,该段将被自动定位到IDATA空间的顶部。……一般不需要特别指定?STACK 的位置,对于具有几个堆栈的汇编程序才需要采用STACK命令。需要注意的是,重新定位?STACK 段必须非常小心,因为可能会破坏 DATA 或 IDATA 空间的变量而导致程序无**常运行。

——摘自《Keil Cx51 V7.0单片机高级语言编程与uVision2应用实践》 徐爱钧编著 P640

冷漠同学啊, 引用就引用吧, 干么断章取义,还夹杂私货, 这样不好嘛。

1)中断堆栈最大可能深度是15(2+5+8)字节, 不是 13。原因已经给出, 不再重复。

2)8051 运行时有只有一个统一stack, 不存在 中断堆栈 以及 非中断堆栈, os 或程序人为操纵stack 另当别论。

3)堆栈段定位在IDATA所有段的最后面, 把空白区全部作为stack 这非常自然, 而且 8051 stack grow *UP*, 用脚后跟想想就会明白。c51:

While the 8051 architecture restricts the stack to internal memory, it may be located at any point therein. The stack typically starts following the last individual variable allocation in internal memory and is free to grow *up* through whatever memory remains.

4)私有堆栈是****编译时*****的中间产物, 用于最后连接计算, 连接时linker 统一定位。目标代码*****运行时*******,只有一个stack. 所有的函数调用, 中断断点, 以及中断register保护都在一个 stack 里。这是最基本的****常识***问题!!!! os 的人为分割切换 stack 完全是另一个概念。

请教 冷漠大师:

您所言的“后台堆栈”,实际上是C语言中的软堆栈,负责分配在全局静态变量空间共享覆盖区,其长度为每个独立的后台函数的私有堆栈之和!
您所言的“前台堆栈”,实际是51单片机中真正的硬件堆栈,负责中断响应需要保护的变量,子函数调用等硬性的压栈出栈操作!

C语言的运行是依靠这一软一硬两个堆栈协调工作,您所言的:一高(端)一低(端),一小一大,一前(台)一后(台)。就是指这一软一硬两个堆栈。

不知俺理解的对不对?

提一个问题:什么是堆栈?

如果,堆栈是指硬件堆栈,那个由堆栈指针SP所控制的,那当然只有一个堆栈,没有什么私有的堆栈,包括中断等,都是往这个堆栈上放,

如果自己在函数里(操作系统也不过是一些函数,一些公用的函数集而已)定义一个堆栈,那个堆栈就不好说,那叫软堆栈。

一个处理系统有且只有一个当前堆栈,就是有SP寄存器控制的那个。不管是中断发生还是函数调用,都是用这个SP定位。其余什么私有堆栈不过是程序修改SP而实现的。
堆栈的深度是不宜精确设置的,除非你的程序很简单,或根本就没有中断嵌套,这样你可以很容易计算出系统可能最大堆栈。不然没什么好说的,将必要的内存设置好,其余的统统留给堆栈(反正闲着也是闲着)。

特地说明一点:
“reentrant"的 "simulated stack" 只是为了模拟通过 stack 传递参数(这是大多数c 编译器的做法)以实现重入,实际实现上有点复杂,是Rn寄存器再加上一个“simulated stack" 数据区(具体情况可以看看反汇编)。这个“simulated stack" 自顶向下, 参数通过 r0, r1或 dptr 存取, 是一个特别数据区, 不是一个真正的 stack,与真正的硬件自动 stack (通过 sp push/pop) 无关.

具体没看过编译手册,不过对于这句有些疑问:
其栈底指针?STACK——由C51自动生成,栈顶应该是IDATA顶端——0xFF

51堆栈是向上生长型,刚开始栈顶应该在栈底那里,每次PUSH,往上加,直到最大0XFF.但是你这里说栈顶应该在IDATA的顶端--OXFF,应该不对。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top