renpeng009672 发表于 2019-10-6 21:04:36

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

本帖最后由 renpeng009672 于 2019-10-6 22:13 编辑

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

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

      while (1)
                {
                        OSWait(K_SIG,0);//等待串口中断发来信号
                        temp1=SBUF0;
                        if (temp==0x55)
                        {
                                if (temp1==0xaa)
                                {
                                        break;
                                }
                               
                        }
                        temp=temp1;
                }
                for (ii=0;ii<NBYTE-2;ii++)
                {..............

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

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

    48:                 while (1)
    49:                 {
    50:                         OSWait(K_SIG,0);
C:0x0592    E4      CLR      A
C:0x0593    FD      MOV      R5,A
C:0x0594    7F01      MOV      R7,#0x01
C:0x0596    12086D    LCALL    _OSWait(C:086D)
    51:                         temp1=SBUF0;
C:0x0599    85991B    MOV      temp1(0x1B),SBUF0(0x99)
    52:                         if (temp==0x55)
C:0x059C    AF08      MOV      R7,temp(0x08)
C:0x059E    EF      MOV      A,R7
C:0x059F    33      RLC      A
C:0x05A0    95E0      SUBB   A,ACC(0xE0)
C:0x05A2    FE      MOV      R6,A
C:0x05A3    EF      MOV      A,R7
C:0x05A4    6455      XRL      A,#0x55
C:0x05A6    4E      ORL      A,R6
C:0x05A7    700D      JNZ      C:05B6/////////////看这里
    53:                         {
    54:                                 if (temp1==0xaa)
C:0x05A9    AF1B      MOV      R7,temp1(0x1B)
C:0x05AB    EF      MOV      A,R7
C:0x05AC    33      RLC      A
C:0x05AD    95E0      SUBB   A,ACC(0xE0)
C:0x05AF    FE      MOV      R6,A
C:0x05B0    EF      MOV      A,R7
C:0x05B1    64AA      XRL      A,#0xAA
C:0x05B3    4E      ORL      A,R6
C:0x05B4    6005      JZ       C:05BB////////////////////还有这里
    55:                                 {
    56:                                         break;
    57:                                 }
    58:                                
    59:                         }
    60:                         temp=temp1;
C:0x05B6    851B08    MOV      temp(0x08),temp1(0x1B)
    61:                 }
C:0x05B9    80D7      SJMP   Uart0(C:0592)
    62:                 for (ii=0;ii<NBYTE-2;ii++)
C:0x05BB    E4      CLR      A

为啥标记的两行不一样捏?然后我改成这样:
       while (1)
                {
                        OSWait(K_SIG,0);
                        temp1=SBUF0;
                        if (temp==0x55)
                        {
                                if (temp1!=0xaa)//////////改成了这样
                                {
                                        break;
                                }
                               
                        }
                        temp=temp1;
                }
                for (ii=0;ii<NBYTE-2;ii++)
                {..............

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

    48:                 while (1)
    49:                 {
    50:                         OSWait(K_SIG,0);
C:0x0592    E4      CLR      A
C:0x0593    FD      MOV      R5,A
C:0x0594    7F01      MOV      R7,#0x01
C:0x0596    12086D    LCALL    _OSWait(C:086D)
    51:                         temp1=SBUF0;
C:0x0599    85991B    MOV      temp1(0x1B),SBUF0(0x99)
    52:                         if (temp==0x55)
C:0x059C    AF08      MOV      R7,temp(0x08)
C:0x059E    EF      MOV      A,R7
C:0x059F    33      RLC      A
C:0x05A0    95E0      SUBB   A,ACC(0xE0)
C:0x05A2    FE      MOV      R6,A
C:0x05A3    EF      MOV      A,R7
C:0x05A4    6455      XRL      A,#0x55
C:0x05A6    4E      ORL      A,R6
C:0x05A7    700D      JNZ      C:05B6/////////////////看这里
    53:                         {
    54:                                 if (temp1!=0xaa)
C:0x05A9    AF1B      MOV      R7,temp1(0x1B)
C:0x05AB    EF      MOV      A,R7
C:0x05AC    33      RLC      A
C:0x05AD    95E0      SUBB   A,ACC(0xE0)
C:0x05AF    FE      MOV      R6,A
C:0x05B0    EF      MOV      A,R7
C:0x05B1    64AA      XRL      A,#0xAA
C:0x05B3    4E      ORL      A,R6
C:0x05B4    7005      JNZ      C:05BB       /////////////还有这里
    55:                                 {
    56:                                         break;
    57:                                 }
    58:                                
    59:                         }
    60:                         temp=temp1;
C:0x05B6    851B08    MOV      temp(0x08),temp1(0x1B)
    61:                 }
C:0x05B9    80D7      SJMP   Uart0(C:0592)
    62:                 for (ii=0;ii<NBYTE-2;ii++)
C:0x05BB    E4      CLR      A


求大神解惑

备注:win7 x86系统       Keil V5.25

1a2b3c 发表于 2019-10-6 21:15:41

这么点判断都会出错的话肯定是你逻辑混乱,先不要啥判断,先把数组打印出来看看到底是啥再说,如果数字内容都不对你咋判断,如果对了,那么再看你的逻辑吧

1a2b3c 发表于 2019-10-6 21:24:25

另外看你的汇编为啥一句判断那么多内容啊,咋没有cjne 那样的简单汇编判断锯子呢,奇怪

wuha 发表于 2019-10-6 22:15:57

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

renpeng009672 发表于 2019-10-6 22:18:05

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

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

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

wuha 发表于 2019-10-6 22:22:13

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

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

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

wye11083 发表于 2019-10-6 23:09:21

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

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

wcl_0308 发表于 2019-10-6 23:30:59

大小端问题?

1a2b3c 发表于 2019-10-7 08:17:20

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

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

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

takashiki 发表于 2019-10-7 08:40:43

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

renpeng009672 发表于 2019-10-7 09:55:01

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

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

页: [1]
查看完整版本: 遇到了一个理解不了的问题,是Keil编译器的BUG吗?