遇到了一个理解不了的问题,是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 这么点判断都会出错的话肯定是你逻辑混乱,先不要啥判断,先把数组打印出来看看到底是啥再说,如果数字内容都不对你咋判断,如果对了,那么再看你的逻辑吧 另外看你的汇编为啥一句判断那么多内容啊,咋没有cjne 那样的简单汇编判断锯子呢,奇怪 我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA,如果你把变量 i 定义为char型,那么因为 i 最大只能到127,所以编译器始终判断二者不相等,后来我把 i 定义为unsigned char,问题解决。 wuha 发表于 2019-10-6 22:15
我没细看楼主程序,但遇到一个类似的串口程序问题,比如判断是否接收的字节付给变量i,然后判断 i==0xAA, ...
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。
我一开始也纳闷,这么简单的语句,反汇编那么复杂,还需要处理借位?然后恍然大悟 renpeng009672 发表于 2019-10-6 22:18
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。
我一开始也纳闷,这么简 ...
说实话,字节型的数据我之前在keil arm编译器里从来都是不加区分的,因为是串口数据处理校验,所以基本上都是判断是否相等,并不判断大小,所以有符号和无符号我始终认为是相等的,因为在存储器里的二进制是一模一样的,也没出过问题,直到移植到51上才发现这个问题。 wuha 发表于 2019-10-6 22:22
说实话,字节型的数据我之前在keil arm编译器里从来都是不加区分的,因为是串口数据处理校验,所以基本上 ...
你真是碰运气了。这在arm上都能正常跑,不容易啊。首先temp就应该定义为unsigned,否则一定会出乱子。 大小端问题? renpeng009672 发表于 2019-10-6 22:18
你发帖之前我也发现了,是用无符号数和有符号数进行比较了。。。。。。。。。。
我一开始也纳闷,这么简 ...
本来就想叫你把代码帖全,想到应该不会那么低级错误吧 :) LZ,很遗憾的告诉你,这个真是编译器的BUG,马老师说过,Keil发布的新版本修正了。
8位不管是有符号还是无符号数都可以自动类型提升为int类型,因此比较是不会出问题的。但是Keil C51这里却出问题了,那么就是Keil的锅,在没有升级编译器之前你只好自己背了。
但如果是int自动提升为unsigned int,那么没的说,程序员的锅没跑。 takashiki 发表于 2019-10-7 08:40
LZ,很遗憾的告诉你,这个真是编译器的BUG,马老师说过,Keil发布的新版本修正了。
8位不管是有符号还是无 ...
你这么一说我想起来了,前段时间还看到马老师的帖子,不过没往心里去。。。{:dizzy:}
页:
[1]