Keil C51里关于堆栈指针的处理
时间:11-17
来源:互联网
点击:
堆栈溢出了!原来这就是导致程序不断重启的原因,不是变量内存溢出,而是堆栈溢出!
而当我把那个数组指定为xdata类型后,由于该数组不再占用idata区,于是IDATA一下子多了16个字节的可用空间,重新编译后的M51这样安排:
IDATA 0080H 0024H UNIT _IDATA_GROUP_
IDATA 00A4H 0022H UNIT ?ID?IPPHONE_MAIN
IDATA 00C6H 001FH UNIT ?ID?DNS_NICRCV?IPPHONE_DNS
IDATA 00E5H 0004H UNIT ?ID?DISP
IDATA 00E9H 0001H UNIT ?STACK
从这组数据来看,SP指针安排到在E9H这个地址,堆栈空间有FFH-E9H+1=23个字节,对于程序来说已经够用,因此程序运行正常。
多次调整变量类型的编译结果表明,C51对于堆栈空间需求大小不作计算,任何代码都只是按堆栈空间只有1个字节需求来分配(在我眼里看来这明显是胡来,稍复杂点的子程序调用都不可能只要1个字节就能完成现场保护),由于堆栈只能分配在data区和idata区,因此当一个程序为了优化而data区占用太多时,虽然编译器能编译成功,但往往SP堆栈指针被分配在data区的最后面,很容易造成堆栈空间不够而溢出。为保险起见,最好保证编译后的SP值安排在F0H之前,那样至少有16个字节的堆栈空间,才能最大限度保证程序不会跑飞。
看样子不能太相信Keil C51,以后编译完后,还得查看一下M51才能确保程序的质量,不知道这个算不算Keil C51的bug。
而当我把那个数组指定为xdata类型后,由于该数组不再占用idata区,于是IDATA一下子多了16个字节的可用空间,重新编译后的M51这样安排:
IDATA 0080H 0024H UNIT _IDATA_GROUP_
IDATA 00A4H 0022H UNIT ?ID?IPPHONE_MAIN
IDATA 00C6H 001FH UNIT ?ID?DNS_NICRCV?IPPHONE_DNS
IDATA 00E5H 0004H UNIT ?ID?DISP
IDATA 00E9H 0001H UNIT ?STACK
从这组数据来看,SP指针安排到在E9H这个地址,堆栈空间有FFH-E9H+1=23个字节,对于程序来说已经够用,因此程序运行正常。
多次调整变量类型的编译结果表明,C51对于堆栈空间需求大小不作计算,任何代码都只是按堆栈空间只有1个字节需求来分配(在我眼里看来这明显是胡来,稍复杂点的子程序调用都不可能只要1个字节就能完成现场保护),由于堆栈只能分配在data区和idata区,因此当一个程序为了优化而data区占用太多时,虽然编译器能编译成功,但往往SP堆栈指针被分配在data区的最后面,很容易造成堆栈空间不够而溢出。为保险起见,最好保证编译后的SP值安排在F0H之前,那样至少有16个字节的堆栈空间,才能最大限度保证程序不会跑飞。
看样子不能太相信Keil C51,以后编译完后,还得查看一下M51才能确保程序的质量,不知道这个算不算Keil C51的bug。
KeilC51堆栈指 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)