我遇到这么一个问题,觉得像是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_v5\C51\BINC 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
那么问题来了,
汇编代码中最后的两次异或运算有何用意?这两次异或运算直接导致第二组数据判断结果不正确!
0