关于51单片机的仿真栈(模拟栈/可重入栈)

本文详细介绍了51单片机的仿真栈,包括系统栈的初始设置、栈溢出问题、keil的处理方式以及仿真栈在可重入函数中的应用。讨论了如何避免栈溢出,以及keil在不同编译模式下对仿真栈的处理,并提醒了不可重入函数可能引发的问题。
摘要由CSDN通过智能技术生成

51单片机的仿真栈(又叫模拟栈、或者可重入栈)。

首先来看,51的系统栈(又叫系统栈,或者硬件栈),就是SP所指向的栈,他是一个满增栈(注释1),位于片内RAM的128 bytes之中,上电之后系统堆栈指针SP的初值等于多少呢?这个要从51的启动文件来分析,启动文件中有这样的汇编代码:

?STACK          SEGMENT   IDATA		;定义一个片内数据段,段名:?STACK
RSEG    ?STACK	;选择之前定义过的一个可重定位的段?STACK,下面的汇编语句将会被放置到该段,直到遇到下一个段定位指令,例如CSEG/RSEG。
DS      1	;预留存储区命令。声明先占用一个字节的空间,在编译时,这个预留的空间不会被其他变量所使用。在这里的意义是,给硬件栈分配1个byte(实际这样是有问题的,应该为硬件栈预留更多空间)

还有:

MOV     SP,#?STACK-1
由上可见,SP被初始化为#?STACK-1,在#?STACK地址处,DS指令预留了N个字节的空间,这些空间就是硬件栈的空间

但启动文件的代码中,DS 1相当于只给硬件栈预留了1个字节,这实际上会出问题,原因如下:片内RAM中会有多个数据段,只要使用XX    SEGMENT   IDATA指令即可在片内RAM中声明一个数据段XX,如果整个工程程序中,声明了多个数据段,?STACK数据段就只是片内RAM中众多数据段中的一个,如果只给?STACK段预留1个字节,而?STACK数据段后面又有别的数据段,那么我们的硬件栈就只有1个字节了,一旦发生中断,CPU寄存器自动入栈立即导致栈溢出,溢出后踩了别的变量的内存,程序基本崩溃;对于这个问题,keil是这样处理的:keil在链接阶段总是把?STACK数据段链接为片内RAM中的最后一个数据段,即使我们只给他预留了1个字节,那也不要紧,反正该段后面没有别的变量占用,只要SP别超出0X7F(片内RAM地址的上限)就行了。通过观察.m51(map文件)我们发现,keil确实是把?STACK数据段放到了片内RAM的最后,下面是某个51工程生成的map文件摘抄:

            * * * * * * *   D A T A   M E M O R Y   * * * * * * *
            REG
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值