gibson08 发表于 2010-7-20 20:50:04

单片机堆栈问题.(这人多哦,就发这了)

今天调C8051单片机程序的时候,发现在子程序调用时,压入堆栈中的数据在子程序执行过程中被改变了,并且其中没有单独对该RAM单元进行操作……然后返回到不正确的位置,这真是太奇怪了……有大侠碰到这类情况的么? 用的Silab公司的编译器.

aaa1982 发表于 2010-7-20 21:33:47

调用函数(ACALL)必然会压栈PC,两个字节。函数返回(ret)的时候出栈PC

这是51框架结构决定的,跟具体的芯片没关系。

silabs也不出编译器,只出了开发环境,编译器还是keil的。

gibson08 发表于 2010-7-20 21:37:14

哦 说错了 就是开发环境。我是说 已经压栈的PC值 在59H 60H 2个单元,在函数没有返回59H就被修改了.然后RET时返回到错误的地址

aaa1982 发表于 2010-7-20 22:06:18

你修改startup文件了么

你的堆栈怎么都到了59H 60H了。

你在你程序开始的时候看一下SP的值是多少。

怎么用了这么大的堆栈空间。

aaa1982 发表于 2010-7-20 22:18:54

startup的 stack段 默认是这样的

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

也就是只保留了一个字节,好像默认SP是0xff,在ram用不了多少的情况下不会出现问题(堆栈从上往下,内存分配从下往上)。

但是如果内存用的比较多可能就出问题了,有一个办法是改变stack段的大小,但是这样可能链接过不了(报告内存不够)。

本来想把idata改成xdaga,好象不行,毕竟sp就是一个8位的地址。

aaa1982

rainyss 发表于 2010-7-20 23:23:41

【4楼】 aaa1982
积分:395
派别:
等级:------
来自:
startup的 stack段 默认是这样的

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

也就是只保留了一个字节,好像默认SP是0xff,在ram用不了多少的情况下不会出现问题(堆栈从上往下,内存分配从下往上)。

但是如果内存用的比较多可能就出问题了,有一个办法是改变stack段的大小,但是这样可能链接过不了(报告内存不够)。

本来想把idata改成xdaga,好象不行,毕竟sp就是一个8位的地址。

aaa1982




堆栈从上往下是谁教你的?把他找来打残先,不光侮辱你智商还侮辱你人格.

gibson08 发表于 2010-7-21 00:02:23

TYPE    BASE      LENGTH    RELOCATION   SEGMENT NAME
            -----------------------------------------------------

            * * * * * * *   D A T A   M E M O R Y   * * * * * * *
            REG   0000H   0008H   ABSOLUTE   "REG BANK 0"
            DATA    0008H   0001H   UNIT         ?DT?S_SOFTRESET?SHT10
                  0009H   0017H                  *** GAP ***
            BIT   0020H.0   0000H.1   UNIT         _BIT_GROUP_
                  0020H.1   0000H.7                *** GAP ***
            DATA    0021H   003EH   UNIT         _DATA_GROUP_
            IDATA   005FH   0001H   UNIT         ?STACK

         这貌似是系统自动生成的,感觉silab的开发环境不好用

aaa1982 发表于 2010-7-21 09:26:45

回复【5楼】rainyss
-----------------------------------------------------------------------

说话太损了哈. 不过确实我说错了.

昨天手头没有程序,我想当然的就认为系统默认把SP放到了Idata的顶部,堆栈是递减的.(有什么是这样的结构么?感觉和什么弄混了)


今天找了个简单的试了一下

            REG   0000H   0008H   ABSOLUTE   "REG BANK 0"
            DATA    0008H   0019H   UNIT         _DATA_GROUP_
            DATA    0021H   0004H   UNIT         ?DT?MAIN
            IDATA   0025H   0001H   UNIT         ?STACK

确实堆栈的递增的. 不好意思误导了一下.


回复【2楼】gibson08
哦 说错了 就是开发环境。我是说 已经压栈的pc值 在59h 60h 2个单元,在函数没有返回59h就被修改了.然后ret时返回到错误的地址
-----------------------------------------------------------------------

1) 带H的应该是16进制吧.(怎么会59H 60H呢,是0x5f,0x60吧)

2) 如果按照你给的map文件,STACK 的范围应该从0x5f(95)开始,存两个地址。现确认这个是正确的吧。你链接的时候有警告么?

gibson08 发表于 2010-7-21 10:34:08

回复【7楼】aaa1982
-----------------------------------------------------------------------

嗯 写错了 5FH
warning C500: LICENSE ERROR (R208: RENEW LICENSE ID CODE (LIC))
这一个警告怎么解决? KEIL在网上下的破解,并且有运行成功的程序。

aaa1982 发表于 2010-7-21 11:30:14

呵呵

不会是keil故意捣乱吧,你方便把程序发上来么,或者直接拿uvision 编译连接一下试试。

这么看不应该出现你说的问题。能定位到哪里修改的STACK么?你的意思是sp没有被改变,但是stack的值改变掉了,是这个意思么?

能定位到那句话改变你的stack的变量了么?
页: [1]
查看完整版本: 单片机堆栈问题.(这人多哦,就发这了)