打印

救火车的火灾预警----小心keil的堆栈隐患。

[复制链接]
楼主: 救火车
手机看帖
扫描二维码
随时随地手机跟帖
81
所长的面对对象弄得不错!

我也要学啊  要写个稍微大点的程序 还得面对对象啊

使用特权

评论回复
82
xuyiyi| | 2010-7-15 22:06 | 只看该作者
引用 冷漠大师的发言:
1、多个非重入函数的参数传递和自动变量是被编译器分配在全局静态变量空间共享覆盖区、而不是堆栈区的(通过堆栈传递参数是纯粹的汇编方法。)因此,整个程序的所有非重入函数所占用的data(C51为例)字节空间是那个使用参数和自动变量最多的函数占有量,其它函数不过是在共享这个区域而已。共享覆盖区被编译器(C51为例)分配在全局变量区的下面。可以看做是后台程序的堆栈(参数及动态变量保护区)。——可以精确计算了吧。这个规则没有疑问吧?关键:
2、由1、可知,前台中断需要保护的变量,和后台非重入函数所占用的“后台堆栈”,没有联系,它仅需要保护自己ISR所用到的寄存器罢了,具体保护哪些寄存器,当然已经由C编译器完成了,无需用户考虑的事。更关键:
3、前台中断ISR所使用的堆栈深度不大于13字节。这已经可以算是中断堆栈深度精确计算了吧。

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

请教大师们,不知俺理解的对不对?

使用特权

评论回复
83
sheriff| | 2010-7-15 22:35 | 只看该作者
谁能解释解释什么叫“硬件自动压入的属于不可控的系统控制栈,STACK根本不指向!”?

使用特权

评论回复
84
sheriff| | 2010-7-15 22:39 | 只看该作者
本帖最后由 sheriff 于 2010-7-15 22:41 编辑

int sum(char a, char b, char c, char d)
{
return a + b + c +d;
}

int sum1(char a, char b, char c, char d)
{
  return(sum(a, b, c, d));
}

int sum2(char a, char b, char c, char d)
{
  return(sum1(a, b, c, d));
}

void isr0(void) interrupt 0
{
  sum2(1,2,3,4);
}
用keil simulater运行,在isr0里堆栈深度为15(不算进入中断时压栈的2字节PC),如何解释?

使用特权

评论回复
85
highgear| | 2010-7-15 22:45 | 只看该作者
顶楼上的警官sheriff

使用特权

评论回复
86
ayb_ice| | 2010-7-16 09:08 | 只看该作者
通常C51只有一个堆栈,就是SP管理有那个IDATA区域
如果使用reentrantr的话会有额外的模拟堆栈,最多会有三个模拟堆栈,分别位于IDATA,PDATA,XDATA区域
但什么ABC三个模块是不会自动产生什么私有堆栈的,除非使用STACK命令,但STACK一般不用,而且只在BL51中提供,LX51根本不提供这个命令

另外根本没有什么"后台堆栈,前台堆栈"这些概念

使用特权

评论回复
87
冷漠| | 2010-7-16 15:21 | 只看该作者
本帖最后由 冷漠 于 2010-7-16 15:58 编辑

86楼真有意思,比过去可是自信多了。说话斩钉截铁,一点后路都不给自己留。是不是也自以为比Keil还聪明?冷漠提醒过你:“什么事给自己留后路。”万一冷漠和其他网友证明了LX51有这个功能,你不好下台呀。   
  
难倒如今也像XXX那样,脸红一次也不在乎,下次还来。2年前就退出论坛,如今回来“昆仑派一点长进都没有。”刚来几天就被人不知道脸红了多少次,反正穿马甲,脸红别人也看不见,反正也不可能长进了,丢脸就丢脸吧,马甲水里拧一把穿上再来。

……LX51根本不提供这个命令
   

谁说LX51不提供这个命令,如若冷漠证明了LX51有这个功能命令,请问86楼你会不会感到脸红?

使用特权

评论回复
88
冷漠| | 2010-7-16 15:22 | 只看该作者

与BL51的STACK命令一样!比STACK还要严格设置。

本帖最后由 冷漠 于 2010-7-16 16:02 编辑

咱也不用总照顾高手的面子了,且看下面证明:



ayb不会像XXX那样寻找一切原因为自己辩解?

抄一段书:“STACK,仅用于BL51,(逗号)对于Lx51应使用CLASSES和SEGMENT命令。”

highgear也不提醒提醒?号称刚看完P640,上面这段话就在P640;看了也白看,(有那点看得懂的水平,早就为LZ找到答案了。还轮得着冷漠在这卖弄?highgear 真是太郁闷了。)不知道 Keil 说什么呢;——自己还没ayb清醒;连张图都贴不出来。还在这混个什么劲。
   
          回家编写总结玩自己精通的专项——C# 或者 BIOS岂不更有价值?谁都不懂呀,这么大中国你头一号,国宝级专家;——用得着在这和菜鸟群里混?认识不到自己的价值,屈才呀!


使用特权

评论回复
89
ayb_ice| | 2010-7-16 16:28 | 只看该作者
本帖最后由 ayb_ice 于 2010-7-16 16:30 编辑

LS
既然STACK命令搞的这么透彻,给大家讲个具体例子
请重点说明
1:什么情况用
2:用有什么好处,不用有什么不好
3:具体怎么用
...

另外LS是否看到KEIL说,一般不需要使用STACK命令
...

使用特权

评论回复
90
sheriff| | 2010-7-16 17:03 | 只看该作者
期待“一级中断堆栈的深度不会大于13字节”的详细讲解,和对本菜鸟84楼提出的问题的解答

使用特权

评论回复
91
ayb_ice| | 2010-7-16 17:18 | 只看该作者
LS

保存ACC,PSW,B,DPH,DPL,R0~R7
加起来就是13字节,其实应该最少还有两个字节的返回地址

使用特权

评论回复
92
冷漠| | 2010-7-16 17:22 | 只看该作者
本帖最后由 冷漠 于 2010-7-16 18:14 编辑

回89楼,88楼的图还不清楚?我在另一楼层抄的书大侠没认真看?

……一般不需要特别指定?STACK的位置,对于具有几个堆栈的汇编程序才需要采用STACK命令。……


88楼特别编写了3个.asm 汇编程序。什么地方用到?救火车版主的问题主要归结为就是:

这个?STACK到底应该离栈顶多远才是安全的?


highgear 大师放了半天卫星:“一定裕量”,“越远越安全”。——K!等于没说啊!这叫高手?冷漠将要论证一星期的不就是辛苦干这个事?

如果仅从程序应用来看,确实不需要玩什么人工设置,L51能够做得很好。连接命令就是为了在这种特殊情况下才需要人工设置的。就像救火车说的情况,我做几十个项目,一次也没遇到过,RTX51内存紧张吧,我没遇到过溢出,连可能都没有。举个例子:

后台多个函数自动变量及参数共享一个覆盖区,当然会有这种情况:要求最好所有函数参数+自动变量的数量都差不多,如若假设有一个特别函数F01 (可重入行不行?),其参数和自动变量之和需要占用50字节,其它后台函数仅需10字节左右共享覆盖,那怎么处理为好?
   也听听大师的意见……贴2张图,示意?STACK的作用:题目借用49楼“英雄无敌六”的题目,那里堆栈用掉22字节,所以这里STACK设0xFF-22>236.。修改一下,把236改设230。可以看到SP_MAX<256,系统堆栈未溢出。

使用特权

评论回复
93
highgear| | 2010-7-16 21:47 | 只看该作者
哈哈,俺基本上看出了问题所在.中文版说的不清楚,而读的人功底不深,又缺乏经验,所以很容易出问题.

这个问题以后俺再说明, 不急.

咳,咳,冷漠同学任何时候都不会放过机会攻击俺,看来俺的pk和技术比拼深深的伤害了冷漠同学那个幼小脆弱的心灵,让祖国的花骨朵蒙羞了.   

使用特权

评论回复
94
linqing171| | 2010-7-18 21:34 | 只看该作者
为什么CCS C可以统计最大堆栈深度?
所以KEIL应该也能统计出来一个。

当然统计出来一个会碰到以下问题:
1 关闭中断,EA=bESave; 这种复杂变量的关中断,确实比较累。
2 可以ISP的函数指针调用,特别老hot大叔经常搞的加密isp什么的。
还会碰到平时静态反汇编都会碰到的问题(比如花指令,加壳)等等。

另外,我提一个思路,用understand生成调用树,在这个调用树上,每个节点都写上本函数占用多少堆栈和执行到本函数占用多少堆栈。

另外说句题外话,keil被arm收购了,keil c51估计以后改进的东西不会很多了,这个东西我们过两年可以挖出来再聊一次,前提是到时候还有人用51,而且还有人用51的汇编。

使用特权

评论回复
95
冷漠| | 2010-7-18 22:02 | 只看该作者
本帖最后由 冷漠 于 2010-7-18 22:04 编辑

linqing 的调用树有道理,冷漠提个问题:能否证明这样一件事:后台调用树中的非重入函数(先不考虑多少层调用),完全不占用?stack 堆栈!(指令PUSH/POP控制的堆栈)( 除了多层调用函数由处理器自动压入堆栈的PC以外)  也就是说:

……每个节点都写上本函数占用多少堆栈……


结果“一定”是0字节!这一点C51编译器规则好像就是这么做的。至今我没发现有违规的例子。——而且,这种人工计算由连接器实现是很简单的事。Keil 有足够的能力做这件事。

由此,完成救火车版主的命题越来越简单了。

使用特权

评论回复
96
highgear| | 2010-7-19 10:05 | 只看该作者
哈哈, 这次俺不发言, 搬个凳子看冷漠表演。

使用特权

评论回复
97
冷漠| | 2010-7-19 10:48 | 只看该作者

预祝所长和少年儿童PK成功 !

本帖最后由 冷漠 于 2010-7-19 11:35 编辑

84楼警长出这道题费了不脑筋吧,可惜警长在中断程序里调用多层嵌套函数的层数太少了!且不说C51允许一个中断ISR内嵌套调用函数的层数受限是多少,先看看您的程序到底用掉了多少字节的堆栈:见下图,应该是才6个字节(深度)没错吧?要超过17可能还要多自创些空函数?——由处理器自动压入的N*2字节PC不算在内,这是警长您自己说的?(它不是由PUSH /POP指令控制的。)否则,中断ISR里嵌套调用100层莫须有自创函数,冷漠钻10回地缝也不够啊。
int sum(char a, char b, char c, char d) { return a + b + c +d; }
int sum1(char a, char b, char c, char d) { return(sum(a, b, c, d)); }
int sum2(char a, char b, char c, char d) { return(sum1(a, b, c, d)); }
void isr0(void) interrupt 0 { sum2(1,2,3,4); }
用keil simulater运行,在isr0里堆栈深度为15(不算进入中断时压栈的2字节PC),如何解释?




所长举双手顶84楼警官程序,一时得意忘了自己亲自做一遍,计算一下。——怕是连 Keil IDE 也不会用,没能力亲自做实验吧!如若不能像冷漠这样,自己做过了,贴的图示清清楚楚,光靠喊能有说服力?“你错啦,你错啦,你就是错啦!……书上也写错啦,教授也翻译错啦,你们都理解错啦,……只有我所长才是对的,“所长天下第一,书上错在哪里,我们理解错在哪里?愿闻其详。”
所长:“我以后给你们讲……”  哈哈,这种人!喊了半天天下人都错了,错在哪又说不出来;那最好安静点,别喊别闹了吧。

又没注意给自己留后路,恐怕今晚上回家又要洗马甲了。有没有再一次失算的感觉?

(冷漠输了永远退出21IC,所长呢?PK应该是对等的。要照这么对等计算,所长不知道要钻多少回地缝了。反正2年前就退出论坛了。如今只要换马甲就行了。)
     如今又把自己的比较对象降级了,只能和儿童级别的“祖国花朵”PK啦?少年儿童们肯定是连555时基电路是什么都不知道,更别说BIOS了。这样PK,取胜的把握大一些是吧。但愿所长这次能够胜算归来。

使用特权

评论回复
98
sheriff| | 2010-7-19 11:13 | 只看该作者
冷漠在阐述观点的时候总夹杂一些技术之外的东西,说其是“夹杂私货”真是抬举他了。;P

使用特权

评论回复
99
ayb_ice| | 2010-7-19 11:31 | 只看该作者
不知所云

使用特权

评论回复
100
冷漠| | 2010-7-19 11:52 | 只看该作者

比起恶意,冷漠只能算幽默。

本帖最后由 冷漠 于 2010-7-19 15:08 编辑

首先是84楼警官“先发制人”做给我看的,冷漠不过是虚心学习,“小巫见大巫”而已;

下回出这样的题目,请事先注明:“我没有恶意。”
85楼所长一顶你,让你的好题目带有了恶意,把你的ID弄脏了。——结果使你的名字带有了恶意和自以为是。认为别人都是错的,只有所长是对的。……自恋没什么不好,每个人多少都有一点自恋。……一旦过度了,就是病态,

感谢警官的抬举,最好还是能把救火车版主的论题解了。那是对冷漠最好的抬举:永远退出21IC。否则,只好把我的签名送给你。

冷漠花时间把84楼的题目动手做了一遍,不过是想看看85楼所长顶这道题目顶在什么地方。所长可不是轻易夸奖别人的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则