OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 51开发者必读!keil C51 V9.59以前的所有版本都有这个BUG!

共7条 1/1 1 跳转至

51开发者必读!keil C51 V9.59以前的所有版本都有这个BUG!

助工
2019-08-21 22:55:21    评分


最新的KEIL C51是V9.59。


在v9.59的 Release Notes 中有一个修正!主要是避免8位有符号数与无符号数比较出错的问题(在少数情况下会发生)

Corrected: in rare cases a signed compare with unsigned char treated the unsigned char as signed. This happens if the unsigned char value results from a calculated assignment. Example:


char i;
unsigned char uc0 = 254;
char c1 = 0;

void main() {
  if (c1 <= (uc0 += c1))    // uc0 is wrongly treated signed => -2 therefore the condition (0 <= -2) is false
    i = 1;
  else
    i = 0;
}

 

对应的汇编语言分析:

Wrong code was generated:
0000 E500        R     MOV     A,uc0
0002 2500        R     ADD     A,c1
0004 F500        R     MOV     uc0,A
0006 D3                SETB    C
0007 6480              XRL     A,#080H       \
0009 F8                MOV     R0,A          |
000A E500        R     MOV     A,c1          |
000C 6480              XRL     A,#080H       |
000E 98                SUBB    A,R0          |
000F 5004              JNC     ?C0001        -> signed char compare
0011 750001      R     MOV     i,#01H
0014 22                RET
0015         ?C0001:
0015 E4                CLR     A
0016 F500        R     MOV     i,A
0018         ?C0003:
0018 22                RET
The correct code is much longer because according to the C standard a cast to int is necessary:
0000 E500        R     MOV     A,uc0
0002 2500        R     ADD     A,c1
0004 FF                MOV     R7,A
0005 F500        R     MOV     uc0,A
0007 AD00        R     MOV     R5,c1         \
0009 ED                MOV     A,R5          |
000A 33                RLC     A             |
000B 95E0              SUBB    A,ACC         |
000D FC                MOV     R4,A          -> cast of signed char to int
000E D3                SETB    C             \
000F ED                MOV     A,R5          |
0010 9F                SUBB    A,R7          |
0011 7480              MOV     A,#080H       +> implicit cast of unsigned char to int
0013 F8                MOV     R0,A          |
0014 6C                XRL     A,R4          |
0015 98                SUBB    A,R0          |
0016 5004              JNC     ?C0001        -> signed int compare
0018 750001      R     MOV     i,#01H
001B 22                RET
001C         ?C0001:
001C E4                CLR     A
001D F500        R     MOV     i,A
001F         ?C0003:
001F 22                RET
To generate smaller code the signedness of the values to be compared should be the same:
...
        if ((unsigned char)c1 <= (uc0 += c1))
...
0000 E500        R     MOV     A,uc0
0002 2500        R     ADD     A,c1
0004 FF                MOV     R7,A
0005 F500        R     MOV     uc0,A
0007 E500        R     MOV     A,c1
0009 D3                SETB    C             \
000A 9F                SUBB    A,R7          |
000B 5004              JNC     ?C0001        -> unsigned char compare
000D 750001      R     MOV     i,#01H
0010 22                RET
0011         ?C0001:
0011 E4                CLR     A
0012 F500        R     MOV     i,A
0014         ?C0003:
0014 22                RET




关键词: V9.59     keil     C51     BUG         

助工
2019-08-21 23:09:53    评分
2楼

我自己一般不把有符号和无符号数直接比较,一直担心这个问题,果然是雷。


助工
2019-08-21 23:12:50    评分
3楼

这确实是非常严重的错误,而且比较底层


助工
2019-08-21 23:14:46    评分
4楼

这个坑有点大。


助工
2019-08-21 23:19:43    评分
5楼

以前没留意,这次明白了!谢楼主分享~


助工
2019-08-23 23:20:23    评分
6楼

下次注意


助工
2019-08-27 23:28:15    评分
7楼

Mark一下 有问题回来翻


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]