搜索
bottom↓
回复: 10

遇到了一个理解不了的问题,是Keil编译器的BUG吗?

[复制链接]

出0入0汤圆

发表于 2019-10-6 21:04:36 | 显示全部楼层 |阅读模式
本帖最后由 renpeng009672 于 2019-10-6 22:13 编辑

我知道哪儿错了。。。。。。。。。拿无符号数和有符号数进行比较了。。。。。。。
编译器没错
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
简单描述如下:

代码用了一个小OS,串口中断里发送信号给串口接收任务,接收任务里从SBUF取数据,一帧数据以  0x55  0xAA  作为开头,接收任务需要判断发来的数据的前两个字节是不是0x55和0xAA

  1.         while (1)
  2.                 {
  3.                         OSWait(K_SIG,0);//等待串口中断发来信号
  4.                         temp1=SBUF0;
  5.                         if (temp==0x55)
  6.                         {
  7.                                 if (temp1==0xaa)
  8.                                 {
  9.                                         break;
  10.                                 }
  11.                                
  12.                         }
  13.                         temp=temp1;
  14.                 }
  15.                 for (ii=0;ii<NBYTE-2;ii++)
  16.                 {..............
复制代码


按理来说,前两个字节是  0x55  0xAA  的话,会运行到break语句,然后执行for (ii=0;ii<NBYTE-2;ii++)....

但是实践表明,完全不是这样。然后我看了一下反汇编代码:

  1.     48:                 while (1)
  2.     49:                 {
  3.     50:                         OSWait(K_SIG,0);
  4. C:0x0592    E4        CLR      A
  5. C:0x0593    FD        MOV      R5,A
  6. C:0x0594    7F01      MOV      R7,#0x01
  7. C:0x0596    12086D    LCALL    _OSWait(C:086D)
  8.     51:                         temp1=SBUF0;
  9. C:0x0599    85991B    MOV      temp1(0x1B),SBUF0(0x99)
  10.     52:                         if (temp==0x55)
  11. C:0x059C    AF08      MOV      R7,temp(0x08)
  12. C:0x059E    EF        MOV      A,R7
  13. C:0x059F    33        RLC      A
  14. C:0x05A0    95E0      SUBB     A,ACC(0xE0)
  15. C:0x05A2    FE        MOV      R6,A
  16. C:0x05A3    EF        MOV      A,R7
  17. C:0x05A4    6455      XRL      A,#0x55
  18. C:0x05A6    4E        ORL      A,R6
  19. C:0x05A7    700D      JNZ      C:05B6  /////////////看这里
  20.     53:                         {
  21.     54:                                 if (temp1==0xaa)
  22. C:0x05A9    AF1B      MOV      R7,temp1(0x1B)
  23. C:0x05AB    EF        MOV      A,R7
  24. C:0x05AC    33        RLC      A
  25. C:0x05AD    95E0      SUBB     A,ACC(0xE0)
  26. C:0x05AF    FE        MOV      R6,A
  27. C:0x05B0    EF        MOV      A,R7
  28. C:0x05B1    64AA      XRL      A,#0xAA
  29. C:0x05B3    4E        ORL      A,R6
  30. C:0x05B4    6005      JZ       C:05BB  ////////////////////还有这里
  31.     55:                                 {
  32.     56:                                         break;
  33.     57:                                 }
  34.     58:                                
  35.     59:                         }
  36.     60:                         temp=temp1;
  37. C:0x05B6    851B08    MOV      temp(0x08),temp1(0x1B)
  38.     61:                 }
  39. C:0x05B9    80D7      SJMP     Uart0(C:0592)
  40.     62:                 for (ii=0;ii<NBYTE-2;ii++)
  41. C:0x05BB    E4        CLR      A
复制代码


为啥标记的两行不一样捏?然后我改成这样:
  1.        while (1)
  2.                 {
  3.                         OSWait(K_SIG,0);
  4.                         temp1=SBUF0;
  5.                         if (temp==0x55)
  6.                         {
  7.                                 if (temp1!=0xaa)  //////////改成了这样
  8.                                 {
  9.                                         break;
  10.                                 }
  11.                                
  12.                         }
  13.                         temp=temp1;
  14.                 }
  15.                 for (ii=0;ii<NBYTE-2;ii++)
  16.                 {..............
复制代码


发送给单片机  0x55  0xAA  ........时就可以正常运行到break。但是,这不是正确的逻辑啊。。。。

  1.     48:                 while (1)
  2.     49:                 {
  3.     50:                         OSWait(K_SIG,0);
  4. C:0x0592    E4        CLR      A
  5. C:0x0593    FD        MOV      R5,A
  6. C:0x0594    7F01      MOV      R7,#0x01
  7. C:0x0596    12086D    LCALL    _OSWait(C:086D)
  8.     51:                         temp1=SBUF0;
  9. C:0x0599    85991B    MOV      temp1(0x1B),SBUF0(0x99)
  10.     52:                         if (temp==0x55)
  11. C:0x059C    AF08      MOV      R7,temp(0x08)
  12. C:0x059E    EF        MOV      A,R7
  13. C:0x059F    33        RLC      A
  14. C:0x05A0    95E0      SUBB     A,ACC(0xE0)
  15. C:0x05A2    FE        MOV      R6,A
  16. C:0x05A3    EF        MOV      A,R7
  17. C:0x05A4    6455      XRL      A,#0x55
  18. C:0x05A6    4E        ORL      A,R6
  19. C:0x05A7    700D      JNZ      C:05B6  /////////////////看这里
  20.     53:                         {
  21.     54:                                 if (temp1!=0xaa)
  22. C:0x05A9    AF1B      MOV      R7,temp1(0x1B)
  23. C:0x05AB    EF        MOV      A,R7
  24. C:0x05AC    33        RLC      A
  25. C:0x05AD    95E0      SUBB     A,ACC(0xE0)
  26. C:0x05AF    FE        MOV      R6,A
  27. C:0x05B0    EF        MOV      A,R7
  28. C:0x05B1    64AA      XRL      A,#0xAA
  29. C:0x05B3    4E        ORL      A,R6
  30. C:0x05B4    7005      JNZ      C:05BB       /////////////还有这里
  31.     55:                                 {
  32.     56:                                         break;
  33.     57:                                 }
  34.     58:                                
  35.     59:                         }
  36.     60:                         temp=temp1;
  37. C:0x05B6    851B08    MOV      temp(0x08),temp1(0x1B)
  38.     61:                 }
  39. C:0x05B9    80D7      SJMP     Uart0(C:0592)
  40.     62:                 for (ii=0;ii<NBYTE-2;ii++)
  41. C:0x05BB    E4        CLR      A
复制代码



求大神解惑

备注:win7 x86系统       Keil V5.25

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入475汤圆

发表于 2019-10-6 21:15:41 来自手机 | 显示全部楼层
这么点判断都会出错的话肯定是你逻辑混乱,先不要啥判断,先把数组打印出来看看到底是啥再说,如果数字内容都不对你咋判断,如果对了,那么再看你的逻辑吧

出0入475汤圆

发表于 2019-10-6 21:24:25 来自手机 | 显示全部楼层
另外看你的汇编为啥一句判断那么多内容啊,咋没有cjne 那样的简单汇编判断锯子呢,奇怪

出0入0汤圆

发表于 2019-10-6 22:15:57 | 显示全部楼层
我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA,如果你把变量 i 定义为char型,那么因为 i 最大只能到127,所以编译器始终判断二者不相等,后来我把 i 定义为unsigned char,问题解决。

出0入0汤圆

 楼主| 发表于 2019-10-6 22:18:05 | 显示全部楼层
wuha 发表于 2019-10-6 22:15
我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA, ...

你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。

我一开始也纳闷,这么简单的语句,反汇编那么复杂,还需要处理借位?然后恍然大悟

出0入0汤圆

发表于 2019-10-6 22:22:13 | 显示全部楼层
renpeng009672 发表于 2019-10-6 22:18
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。

我一开始也纳闷,这么简 ...

说实话,字节型的数据我之前在keil arm编译器里从来都是不加区分的,因为是串口数据处理校验,所以基本上都是判断是否相等,并不判断大小,所以有符号和无符号我始终认为是相等的,因为在存储器里的二进制是一模一样的,也没出过问题,直到移植到51上才发现这个问题。

出0入442汤圆

发表于 2019-10-6 23:09:21 来自手机 | 显示全部楼层
wuha 发表于 2019-10-6 22:22
说实话,字节型的数据我之前在keil arm编译器里从来都是不加区分的,因为是串口数据处理校验,所以基本上 ...

你真是碰运气了。这在arm上都能正常跑,不容易啊。首先temp就应该定义为unsigned,否则一定会出乱子。

出0入0汤圆

发表于 2019-10-6 23:30:59 来自手机 | 显示全部楼层
大小端问题?

出0入475汤圆

发表于 2019-10-7 08:17:20 来自手机 | 显示全部楼层
renpeng009672 发表于 2019-10-6 22:18
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。

我一开始也纳闷,这么简 ...

本来就想叫你把代码帖全,想到应该不会那么低级错误吧 :)

出0入93汤圆

发表于 2019-10-7 08:40:43 | 显示全部楼层
LZ,很遗憾的告诉你,这个真是编译器的BUG,马老师说过,Keil发布的新版本修正了。
8位不管是有符号还是无符号数都可以自动类型提升为int类型,因此比较是不会出问题的。但是Keil C51这里却出问题了,那么就是Keil的锅,在没有升级编译器之前你只好自己背了。
但如果是int自动提升为unsigned int,那么没的说,程序员的锅没跑。

出0入0汤圆

 楼主| 发表于 2019-10-7 09:55:01 | 显示全部楼层
takashiki 发表于 2019-10-7 08:40
LZ,很遗憾的告诉你,这个真是编译器的BUG,马老师说过,Keil发布的新版本修正了。
8位不管是有符号还是无 ...

你这么一说我想起来了,前段时间还看到马老师的帖子,不过没往心里去。。。

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 06:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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