找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1324|回复: 12
收起左侧

关于堆栈和ram的问题

[复制链接]
ID:1039663 发表于 2024-10-31 11:14 | 显示全部楼层 |阅读模式
rt,51单片机中的用户ram是从30h-7fh,堆栈也是在这个区域中,有几个问题;1.请问如果用push/pop的堆栈区域的总容量是多少?是直接从30h开始连续存放吗?如果是这样的话那么通过直接寻址就能访问到堆栈中元素了,是不是和堆栈思想不符?
2. 堆栈的容量是固定的吗,会小于整体用户ram区容量吗?如果是的话如果自己用ram中非堆栈区作为自己的临时变量应该从多少地址开始?

谢谢

回复

使用道具 举报

ID:1109793 发表于 2024-10-31 17:57 | 显示全部楼层
用C,不用关心这些吧
回复

使用道具 举报

ID:624769 发表于 2024-10-31 18:36 | 显示全部楼层
51单片机的堆栈 存放起始位置 由 寄存器 SP 设定。
通常,如果C语言编译,并且加载了 STARTUP.A51 引导程序,SP默认为 用于变量声明结束后位置。
至于堆栈容量多大,站在51单片机的硬件角度看,理论上可以最大256字节,当然,这是理论上。实际应用时寄存器组最少需要8个字节,那么,即使你的代码中没有声明任何变量,堆栈也只有248字节了,加上如果用的 AT89C51 RAM只有128 那么,实际堆栈可使用最大容量只有120字节。
又因为堆栈只能顺序往后递增,一旦你有声明 位 变量,必须占用 20H 字节地址,那么 堆栈最少要从 21H 位置开始,这样可以使用的堆栈容量最大只有95字节。
回复

使用道具 举报

ID:1039663 发表于 2024-10-31 19:51 | 显示全部楼层
188610329 发表于 2024-10-31 18:36
51单片机的堆栈 存放起始位置 由 寄存器 SP 设定。
通常,如果C语言编译,并且加载了 STARTUP.A51 引导程 ...

请问如果是汇编呢?
回复

使用道具 举报

ID:517466 发表于 2024-10-31 21:23 | 显示全部楼层
汇编也好,C也好,都涉及SP的设置。只不过C中帮你做了处理。在汇编中,你需要根据程序中中断的多少,子程序的嵌套调用级数,确定堆栈的深度。中断处理越多,子程序嵌套越多,就越需要堆栈的深度。
回复

使用道具 举报

ID:401564 发表于 2024-11-1 00:19 | 显示全部楼层
1,堆栈区域的总容量是多少?
这并不重要,重要的是你要了解单片机编程的原理,对于8051而言,30h-7fh都可以
但一个合格的单片机C语言程序,16层的堆栈几乎能应对99.9%的程序,再不行可以用32层
也就是
MOV SP, #5FH
如果你还不明白我说的是什么,那就得再去看一上单片机编程的原理,因为,并不是所有的单片机都是像51这样,用软件堆栈的,有的是硬件堆栈,而且只有4层,如果你不了解其中的原理,到时候写起代码来,问题很多的
2,这个问题参考上面的回答就可以了
回复

使用道具 举报

ID:1073939 发表于 2024-11-1 09:23 | 显示全部楼层
1. 51的堆栈通常安排在ram区的最后区域,一般情形下有30个字节够用了,即60h-7fh(或e0h-ffh),堆栈容量当然越大越好。
2. c编译器会自动安排,把未用到的ram全部用作堆栈。你只要确认编译后用到的的data区小于96(或220)字节,否则要修改代码。
汇编非常灵活,堆栈可安排在20H后的任意区域。假如按C编译器的做法(推荐),自己的临时变量是从地址20h开始。
回复

使用道具 举报

ID:1039663 发表于 2024-11-1 20:57 | 显示全部楼层
Y_G_G 发表于 2024-11-1 00:19
1,堆栈区域的总容量是多少?
这并不重要,重要的是你要了解单片机编程的原理,对于8051而言,30h-7fh都可以
...

我之前是使用8086汇编的,在调用子程序的时候需要进行保护现场和恢复现场,会用到很多的堆栈来干这个事,请问51中也是需要这样做吗?我看很多的视频和教材里都是只保存PC和PSW
回复

使用道具 举报

ID:401564 发表于 2024-11-1 22:46 | 显示全部楼层
首先,你要知道单片机选择汇编的原因
1,之前版本的稳定量产程序是汇编的,新产品只要稍稍改一小部分就可以生产的
2,片上资源实在太少了,比如,RAM只48B这种的低端单片机
3,单片机本身就没有C编译器,只能用汇编
4,对时序要求非常严格的,精确到一个时钟的程序
除了以上说的,没有其它理由再选择汇编了,相信我,我用了3年的汇编,现在用C了
回复

使用道具 举报

ID:401564 发表于 2024-11-1 22:58 | 显示全部楼层
教材里都是只保存PC和PSW,那是因为没有用到其它的地址,其它地址的数据没有什么改变,不需要做什么事情
如果累加器A在别的子程序中用到,而中断中也用到A的话,这个时候就要保存A了,同理,R2-R7也一样的
只要中断服务中断外的子程序都用到一个地址的时候,中断就要进行现场保护
对于你而言,我建议是放弃汇编,去用C,如果不会C,也可能现在开始学C,可能刚开始的时候有点不习惯,但是,不管是现在还是将来,C一定是单片机最好的选择,熟练C要比熟练汇编好上很多倍
上古时期的东西,不需要学,不要迷恋网上说的那些汇编的好处,也不要觉得汇编是基础,必需要学的
没有必要,你看现在,谁还学机器语言,操作码的
回复

使用道具 举报

ID:624769 发表于 2024-11-2 00:42 | 显示全部楼层
zjm001 发表于 2024-11-1 20:57
我之前是使用8086汇编的,在调用子程序的时候需要进行保护现场和恢复现场,会用到很多的堆栈来干这个事, ...

51而言,PC是硬件层直接 入栈的,会占用堆栈的两个字节,但是,不需要你手动去操作,当你 CALL 的时候,就入栈,RET的时候 就自动出栈,同理当中断触发时,PC会自动入栈,当执行到 RETI时就会自动出栈。而其他的寄存器,比如,PSW, ACC, DPTR 这些,就要你自己手动的一个个 PUSH 和 POP了。至于保存哪些,取决于你的子程序 需要用到哪些,比如,你的子程序中 需要 执行,MOVC   A,@A+DPTR  那么,你肯定需要把 ACC, DPL, DPH 都入栈了,
回复

使用道具 举报

ID:384109 发表于 2024-11-2 08:48 | 显示全部楼层
你可以看看51的教材,你说使用过8086的汇编,那么你所提的问题也就是说你没有看过51的教材,关于51的堆栈,教材中是一定会有说明的
回复

使用道具 举报

ID:349276 发表于 2024-11-2 12:43 来自触屏版 | 显示全部楼层
栈是为临时变量开辟的区域,大小应该不能固定。因为涉及函数调用,嵌套层数多,空间就用得多。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表