打印
[STM8]

哭死哦,遇到如此变态的iar for stm8的bug

[复制链接]
7187|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
donkey89|  楼主 | 2011-8-11 10:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 donkey89 于 2011-8-11 11:53 编辑

过程很简单,功能就是把十六进制数缩小1万倍,变成十进制的字符串,例如数值15030,转换过来就是"15.030".但是居然能影响到另外一个毫不相干的函数的运行结果,我在过程的各个地方都加了限定条件,不会出现越界访问的情况
重点看
第48行
str[j++]=(char)(val/m)+'0';
把这个注释掉或者把J++变成立即数都不会再出现问题了.例如
str[5]=(char)(val/m)+'0';

代码没法跟踪,到那一段自动非法错误退出
//******************
//功能:调用hex2str并显示到lcd上
//*******************
void lcd_printf_int(uint16_t n)
{
  char str[9];//这个数组足够大了,实际仅仅用到7个字节而已
//  char i;
//  i=sprintf(str,"%d",n);
//  if(i>8) str[8]='\0';
  hex2str(n,str);
  lcd_puts(str);
}

//***********************
//功能:数值转换成字符串的函数
//参数n:要转换的数
//参数str:转换结果存储的地方
//************************
void hex2str(uint16_t n,char *str)
{
  uint16_t val,m;
  char i,j;
  
  m=10000;
  val=n;
  j=0;
  for(i=0;i<2;i++)
  {
    if(val>=m)
    {
      str[j++]=(char)(val/m)+'0';
      val%=m;
    }
    else if(val<n)
      str[j++]='0';
    m/=10;
  }
  if(j==0)
      str[j++]='0';
  str[j++]='.';
//*************以上处理的是大于1的部分**************
  
  for(;i<5;i++)
  {
    if(val>=m)
    {
      if(j<6)
        str[j++]=(char)(val/m)+'0';//这里,如果把J++换成<5的立即数,就不会影响另外一个完全不相关的函数
      val%=m;
    }
    else if(j<6)
      str[j++]='0';   
    m/=10;
  }
//*************小数点部分*************
  
  str[6]='\0';
}
沙发
wangjckj| | 2011-8-11 11:06 | 只看该作者
这样类似的问题在IAR STM8 中经常见到,估计还是不成熟。我都见惯不怪了

使用特权

评论回复
板凳
上官金虹| | 2011-8-11 11:20 | 只看该作者
堆栈是否足够?
你的影响到额外不相关函数是什么函数?

使用特权

评论回复
地板
donkey89|  楼主 | 2011-8-11 11:32 | 只看该作者
本帖最后由 donkey89 于 2011-8-11 11:46 编辑

2楼,你遇到这种情况怎么绕开?

3# 上官金虹
heap的大小为256字节,堆栈为256字节,怎么会不够?
我重新设置了更大的heap和stack,依然不行

使用特权

评论回复
5
wangjckj| | 2011-8-11 11:36 | 只看该作者
3#
堆栈绝对没问题!

4#
解决办法就是调整代码重新编译。

使用特权

评论回复
6
香水城| | 2011-8-11 12:37 | 只看该作者
会不会有代码重入的问题?

使用特权

评论回复
7
yinyangdianzi| | 2011-8-11 13:06 | 只看该作者
节哀

使用特权

评论回复
8
donkey89|  楼主 | 2011-8-11 13:22 | 只看该作者
6# 香水城
妹哦,代码就在一楼,你看看有没有可以重入的地方?希望你能找出来,这样帮了我一个大忙了.还可以让大家引以为戒

使用特权

评论回复
9
上官金虹| | 2011-8-11 18:44 | 只看该作者
你的影响到额外不相关函数是什么函数?

使用特权

评论回复
10
donkey89|  楼主 | 2011-8-11 20:30 | 只看该作者
本帖最后由 donkey89 于 2011-8-11 20:34 编辑

9# 上官金虹
运算函数,根据AD值,然后经过特殊算法得到一个值
字符串转换函数我跟踪进去就崩溃.看反汇编没有ret,不知道跳到哪去了.屏蔽掉代码重新编译可以看到ret指令.
整个转换函数我在其他编译器上测试通过了,才拷贝过来用的.

使用特权

评论回复
11
ccmc| | 2011-8-11 22:28 | 只看该作者
算术越界了........?

使用特权

评论回复
12
linqing171| | 2011-8-12 07:13 | 只看该作者
经过详细核对,发现
1: 运算过程稍微复杂。
2: 运算输出结果完全正确,包括各种数据输入情况下。
3: 无除以0等操作的可能。
4: 数组无溢出可能。堆栈使用固定,不可能到最后面的时候采出错。

烦请楼主贴list文件,看汇编怎么回事。

使用特权

评论回复
13
香水城| | 2011-8-12 09:39 | 只看该作者
6# 香水城
妹哦,代码就在一楼,你看看有没有可以重入的地方?希望你能找出来,这样帮了我一个大忙了.还可以让大家引以为戒
donkey89 发表于 2011-8-11 13:22


比如讲,这个运算就不是可重入的:(val/m)

使用特权

评论回复
14
yewuyi| | 2011-8-12 09:43 | 只看该作者
搞不懂LZ这么写有什么优点。

1、首先LZ弄错了,‘例如数值15030,转换过来就是"15.030".’,这是缩小1000倍。
2、看LZ好像是送LCD显示,如果是俺,宁可这样写:
d1=val/10000;
d2=(val%10000)/1000;
d3=(val%1000)/100;
d4=(val%100)/10;
d5=val%10;
多简单明了,如果想转换成字符串,上面的d1~d5转换一下非常容易。

使用特权

评论回复
15
donkey89|  楼主 | 2011-8-16 08:55 | 只看该作者
14# yewuyi
您的代码很直观,我这么写是为了省空间而已,空间不够用了.我试试你的写法看看能不能省空间.
其实我对C嵌入汇编不熟,否则直接用汇编了.

使用特权

评论回复
16
t.jm| | 2011-8-16 09:13 | 只看该作者
if(j<6)

        str[j++]=(char)(val/m)+'0';//这里,如果把J++换成<5的立即数,就不会影响另外一个完全不相关的函数
....
m/=10;

肯定是0除了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:数显ESR电容等效内阻测量仪 http://cn.digit-esr.com

241

主题

1609

帖子

1

粉丝