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

2020-01-12 17:19发布

本帖最后由 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
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
10条回答
1a2b3c
1楼-- · 2020-01-12 19:46
这么点判断都会出错的话肯定是你逻辑混乱,先不要啥判断,先把数组打印出来看看到底是啥再说,如果数字内容都不对你咋判断,如果对了,那么再看你的逻辑吧
1a2b3c
2楼-- · 2020-01-13 01:37
 精彩回答 2  元偷偷看……
wuha
3楼-- · 2020-01-13 06:38
我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA,如果你把变量 i 定义为char型,那么因为 i 最大只能到127,所以编译器始终判断二者不相等,后来我把 i 定义为unsigned char,问题解决。
renpeng009672
4楼-- · 2020-01-13 10:24
wuha 发表于 2019-10-6 22:15
我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA, ...

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

我一开始也纳闷,这么简单的语句,反汇编那么复杂,还需要处理借位?然后恍然大悟
wuha
5楼-- · 2020-01-13 12:28
renpeng009672 发表于 2019-10-6 22:18
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。

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

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

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

一周热门 更多>