找回密码
 立即注册
查看: 171|回复: 9

栈顶地址怎么看

[复制链接]
已绑定手机

5

主题

34

回帖

341

积分

中级会员

积分
341
发表于 2026-9-15 20:29:44 | 显示全部楼层 |阅读模式
下面是试验箱中的跑马灯,我想问一下大家,类似汇编语言的 MOV SP, #80H, 在下面程序中栈顶地址怎么看
  1. #include "stc8h.h"       //包含此头文件后,不需要再包含"reg51.h"头文件
  2. #define     MAIN_Fosc       24000000L   //定义主时钟
  3. /*************  功能说明    **************
  4. 本例程基于STC8H8K64U为主控芯片的实验箱进行编写测试,STC8G、STC8H系列芯片可通用参考.
  5. 程序使用P6口来演示跑马灯,输出低驱动。
  6. 当用户使用硬件 USB 对 STC8H8K64U 系列进行 ISP 下载时不能调节内部 IRC 的频率,
  7. 但用户可用选择内部预置的 16 个频率
  8. (分别是 5.5296M、 6M、 11.0592M、 12M、 18.432M、 20M、 22.1184M、
  9. 24M、27M、 30M、 33.1776M、 35M、 36.864M、 40M、 44.2368M 和 48M)。
  10. 下载时用户只能从频率下拉列表中进行选择其中之一,而不能手动输入其他频率。
  11. (使用串口下载则可用输入 4M~48M 之间的任意频率)。
  12. 下载时, 选择时钟 24MHZ (用户可自行修改频率).
  13. ******************************************/
  14. typedef     unsigned char   u8;
  15. typedef     unsigned int    u16;
  16. typedef     unsigned long   u32;
  17. u8 xdata ledIndex;
  18. u8 code ledNum[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  19. void  delay_ms(u8 ms);
  20. /******************** 主函数 **************************/
  21. void main(void)
  22. {
  23.     P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能
  24.     P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  25.     P1M1 = 0x30;   P1M0 = 0x30;   //设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
  26.     P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
  27.     P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
  28.     P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
  29.     P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
  30.     P6M1 = 0x00;   P6M0 = 0xff;   //设置为推挽输出
  31.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  32.     P40 = 0;        //LED Power On
  33.     ledIndex = 0;
  34.     while(1)
  35.     {
  36.         P6 = ~ledNum[ledIndex];    //输出低驱动
  37.         ledIndex++;
  38.         if(ledIndex > 7)
  39.         {
  40.             ledIndex = 0;
  41.         }
  42.         delay_ms(250);
  43.         delay_ms(250);
  44.     }
  45. }
  46. //========================================================================
  47. // 函数: void delay_ms(u8 ms)
  48. // 描述: 延时函数。
  49. // 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
  50. // 返回: none.
  51. // 版本: VER1.0
  52. // 日期: 2021-3-9
  53. // 备注:
  54. //========================================================================
  55. void delay_ms(u8 ms)
  56. {
  57.      u16 i;
  58.      do{
  59.           i = MAIN_Fosc / 10000;
  60.           while(--i);   //10T per loop
  61.      }while(--ms);
  62. }
复制代码




回复

使用道具 举报 送花

9

主题

772

回帖

5311

积分

论坛元老

积分
5311
发表于 2026-9-15 21:12:48 | 显示全部楼层
C编译器会自动分配堆栈,用户一般不用关心具体地址,特殊情况可以看list输出的汇编文件里找具体堆栈位置
回复

使用道具 举报 送花

已绑定手机

5

主题

34

回帖

341

积分

中级会员

积分
341
 楼主| 发表于 2026-9-16 13:14:38 | 显示全部楼层
我看了一下跑马灯的list文件,没有关于栈的描述,是不是可以这样理解,对于编译结果Program Size: data=9.0 xdata=1 code=135,data不能超过128,栈实际占用的是超过128到256之间的ram,请各位指点一下,
  1. MODULE INFORMATION:   STATIC OVERLAYABLE
  2.    CODE SIZE        =    112    ----
  3.    CONSTANT SIZE    =      8    ----
  4.    XDATA SIZE       =      1    ----
  5.    PDATA SIZE       =   ----    ----
  6.    DATA SIZE        =   ----    ----
  7.    IDATA SIZE       =   ----    ----
  8.    BIT SIZE         =   ----    ----
  9. END OF MODULE INFORMATION.
复制代码
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-16 17:56:17 | 显示全部楼层
我查了下AI,回答是这样的,不知道对吗:

STC8H8K64U 单片机中
1,默认值‌:单片机上电或复位后,SP 的初始值通常为 ‌0x07‌。
为什么是0x07,因为:
  工作寄存器组‌:低 128 字节的前 32 个字节(0x00-0x1F)被划分为 4 组工作寄存器(R0-R7)。默认使用第 0 组(0x00-0x07)。
2,STC8H8K64U 的栈只能建立在‌片内低 128 字节 RAM‌(Direct Addressing RAM, 地址 0x00-0x7F)中。
3,栈空间‌:从 0x08 开始向上增长。如果程序中使用了多组寄存器或大量局部变量,需要特别注意栈不要覆盖正在使用的寄存器或变量区域。
STC8H8K64U 的低 128 字节 RAM 非常有限。如果嵌套调用层级过深、中断嵌套过多或局部变量过大,SP 可能超过 0x7F
一旦 SP 超过 0x7F,栈操作将进入高 128 字节 RAM 或 SFR 区域,这会导致‌不可预测的行为
4,在某些情况下,开发者可以在初始化代码中手动修改 SP 的值,以避开特定的内存区域。例如,如果希望栈从 0x30 开始(避开前几组寄存器和位寻址区),可以执行 MOV SP, #0x2F。这样第一个压栈数据将存入 0x30。
5,推荐做法‌:通常保持默认 SP=0x07 即可,但需确保全局变量和静态变量不占用 0x08-0x7F 中与栈重叠的部分。
编译器(如 Keil C51)通常会自动分析并分配变量地址,避免与栈冲突。
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-16 18:02:43 | 显示全部楼层
map文件中有栈的地址信息,
Listing目录下的 xx项目名.map,如下是我的一个ai8051u的,
截图202609161802194739.jpg
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-16 18:07:32 | 显示全部楼层
看了下我的ai8051u中的map, 栈好像是这样分配的:
edata中先分配好所有edata类型的变量的占用,之后就是栈的开始位置了,长256;
回复

使用道具 举报 送花

已绑定手机

5

主题

34

回帖

341

积分

中级会员

积分
341
 楼主| 发表于 2026-9-17 10:35:39 | 显示全部楼层
好的,谢谢大家回复,.M51文件中,可以看到编译器分配的栈顶地址是08H
  1.             TYPE    BASE      LENGTH    RELOCATION   SEGMENT NAME
  2.             -----------------------------------------------------
  3.             * * * * * * *   D A T A   M E M O R Y   * * * * * * *
  4.             REG     0000H     0008H     ABSOLUTE     "REG BANK 0"
  5.             IDATA   0008H     0001H     UNIT         ?STACK
复制代码


回复

使用道具 举报 送花

已绑定手机

5

主题

34

回帖

341

积分

中级会员

积分
341
 楼主| 发表于 2026-9-17 13:28:14 | 显示全部楼层
jrc*** 发表于 2026-9-16 18:02
map文件中有栈的地址信息,
Listing目录下的 xx项目名.map,如下是我的一个ai8051u的,
...

你这个怎么是10cH开始的,超过255了
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-9-17 15:48:01 | 显示全部楼层
ckhz*** 发表于 2026-9-17 13:28
你这个怎么是10cH开始的,超过255了

ai8051u可以栈可以超255,最大可达2k; 具体是以edata的大小来定。
回复

使用道具 举报 送花

已绑定手机

5

主题

34

回帖

341

积分

中级会员

积分
341
 楼主| 发表于 2026-9-17 16:33:25 | 显示全部楼层
jrc*** 发表于 2026-9-17 15:48
ai8051u可以栈可以超255,最大可达2k; 具体是以edata的大小来定。

好的,没有接触过ai8051,先学习一下
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-8 03:09 , Processed in 0.076778 second(s), 83 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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