完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我遇到这么一个问题,觉得像是Keil的一个bug!问题描述如下:
51单片机是8bitMCU,没有操作16bit数据的指令,如果要将两个16bit的数据比较大小,Keil编译器会对其使用一个算法进行比较。 下面是16bit数据比较的C语言代码: [C] 纯文本查看 复制代码 /*IDE-Version:?Vision V5.11.2.0Copyright (C) 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.Tool Version Numbers:Toolchain: PK51 Prof. Developers Kit Version: 9.53.0.0Toolchain Path: D:Keil_v5C51BINC Compiler: C51.exe V9.53.0.0Assembler: A51.exe V8.02bLinker/Locator: BL51.exe V6.22Librarian: LIB51.exe V4.30.0.2Hex Converter: OH51.exe V2.7.0.0CPU DLL: S8051.DLL V3.95.0.0Dialog DLL: DP51.DLL V2.62.0.1Target DLL: STCMON51.DLL V1, 0, 3, 0Dialog DLL: TP51.DLL V2.58*/***it CY = 0xD7;main(){unsigned char xdata data1_L=0x03;unsigned char xdata data1_H=0x6A;unsigned char xdata data2_L=0x0A;unsigned char xdata data2_H=0x7A;unsigned char xdata tmp=5;while(1){if(((data1_H<<8)+data1_L) <= ((data2_H<<8)+data2_L)){tmp++;}}}这段C语言16bit数据比较部分的汇编代码如下: [C] 纯文本查看 复制代码 0014 900000 R MOV DPTR,#data2_H0017 E0 MOVX A,@DPTR0018 FE MOV R6,A0019 900000 R MOV DPTR,#data2_L001C E0 MOVX A,@DPTR001D 7C00 MOV R4,#00H001F 2400 ADD A,#00H0021 FD MOV R5,A0022 EC MOV A,R40023 3E ADDC A,R60024 FC MOV R4,A0025 900000 R MOV DPTR,#data1_H0028 E0 MOVX A,@DPTR0029 FE MOV R6,A002A 900000 R MOV DPTR,#data1_L002D E0 MOVX A,@DPTR002E 7A00 MOV R2,#00H0030 2400 ADD A,#00H0032 FF MOV R7,A0033 EA MOV A,R20034 3E ADDC A,R60035 FE MOV R6,A0036 D3 SETB C0037 EF MOV A,R70038 9D SUBB A,R50039 EC MOV A,R4003A 6480 XRL A,#080H003C F8 MOV R0,A003D EE MOV A,R6003E 6480 XRL A,#080H0040 98 SUBB A,R00041 50D1 JNC ?C0001这个比较是成立的,tmp变量实现了加1。但是当比较值为如下的时候: 第二组数据: [C] 纯文本查看 复制代码 unsigned char xdata data1_L=0x03;unsigned char xdata data1_H=0x6A;unsigned char xdata data2_L=0x0A;unsigned char xdata data2_H=0xFA; C代码中的比较语句是不成的,也就是说,tmp没有加1。那段汇编代码的大意就是: data1的LSB减去data2的LSB,标记借位CY。data1的MSB减去data2的MSB减去上一次减法的借位CY。 如果当前借位CY为0证明data1>=data2,CY为1证明data1 汇编代码中最后的两次异或运算有何用意?这两次异或运算直接导致第二组数据判断结果不正确! |
|
相关推荐
5个回答
|
|
问题已解决。这不是Keil的bug,详细原因如下:
对于移位操作符 << 或者 >>,这是双目操作符,有两个操作数。在C标准中规定,移位时被移位数(左操作数)有个类型转换,规则如下: 如果左操作数当前类型的有符号数范围小于高于其类型一级(int > short > char)的有符号数的范围,那么操作数当前类型的无符号数会转换为高一级类型的有符号数。在这里就是,unsigned char类型的数据左移8位,类型转换为short类型,然后unsigned char类型的数据再加short类型的数据,最终结果就是一个有符号的short类型的数据。这也就解释了最初那段C的汇编在比较MSB时,对其进行异或运算。 |
|
|
|
帮顶。。。。
|
|
|
|
受宠若惊( ⊙ o ⊙ )
|
|
|
|
补充:
同样的环境,当C语言的写如下的时候 [C] 纯文本查看 复制代码 unsigned short xdata data1 = 0x6A0A;unsigned short xdata data2 = 0xFA03;if(data1 <= data2){tmp++;}不论何种数据组合,比较结果都是正确的。他的汇编代码如下: [C] 纯文本查看 复制代码 0059 900000 R MOV DPTR,#data2005C E0 MOVX A,@DPTR005D FE MOV R6,A005E A3 INC DPTR005F E0 MOVX A,@DPTR0060 FF MOV R7,A0061 D3 SETB C0062 900000 R MOV DPTR,#data1+01H0065 E0 MOVX A,@DPTR0066 9F SUBB A,R70067 900000 R MOV DPTR,#data1006A E0 MOVX A,@DPTR006B 9E SUBB A,R6006C 50BB JNC ?C0001这段汇编的大意和之前的一样,不过少了最后的两个异或运算。 之前的C语言写法,会导致某些数据的比较出错,不知是编译器的bug还是编译器有啥特别的想法。 |
|
|
|
你研究的也太深太没必要了吧,两个数字比较大小都能有bug她还能用到现在吗
|
|
|
|
只有小组成员才能发言,加入小组>>
3311 浏览 9 评论
2994 浏览 16 评论
3493 浏览 1 评论
9058 浏览 16 评论
4087 浏览 18 评论
1176浏览 3评论
604浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
598浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2334浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1895浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 21:25 , Processed in 1.347066 second(s), Total 89, Slave 69 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号