我遇到这么一个问题,觉得像是Keil的一个bug!问题描述如下:
51单片机是8bitMCU,没有操作16bit数据的指令,如果要将两个16bit的数据比较大小,Keil编译器会对其使用一个算法进行比较。
下面是16bit数据比较的C语言代码:
[mw_shl_code=c,true]/*
IDE-Version:
?Vision V5.11.2.0
Copyright (C) 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.
Tool Version Numbers:
Toolchain: PK51 Prof. Developers Kit Version: 9.53.0.0
Toolchain Path: D:\Keil_v5\C51\BIN
C Compiler: C51.exe V9.53.0.0
Assembler: A51.exe V8.02b
Linker/Locator: BL51.exe V6.22
Librarian: LIB51.exe V4.30.0.2
Hex Converter: OH51.exe V2.7.0.0
CPU DLL: S8051.DLL V3.95.0.0
Dialog DLL: DP51.DLL V2.62.0.1
Target DLL: STCMON51.DLL V1, 0, 3, 0
Dialog DLL: TP51.DLL V2.58
*/
sbit 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++;
}
}
}[/mw_shl_code]
这段C语言16bit数据比较部分的汇编代码如下:
[mw_shl_code=c,true]0014 900000 R MOV DPTR,#data2_H
0017 E0 MOVX A,@DPTR
0018 FE MOV R6,A
0019 900000 R MOV DPTR,#data2_L
001C E0 MOVX A,@DPTR
001D 7C00 MOV R4,#00H
001F 2400 ADD A,#00H
0021 FD MOV R5,A
0022 EC MOV A,R4
0023 3E ADDC A,R6
0024 FC MOV R4,A
0025 900000 R MOV DPTR,#data1_H
0028 E0 MOVX A,@DPTR
0029 FE MOV R6,A
002A 900000 R MOV DPTR,#data1_L
002D E0 MOVX A,@DPTR
002E 7A00 MOV R2,#00H
0030 2400 ADD A,#00H
0032 FF MOV R7,A
0033 EA MOV A,R2
0034 3E ADDC A,R6
0035 FE MOV R6,A
0036 D3 SETB C
0037 EF MOV A,R7
0038 9D SUBB A,R5
0039 EC MOV A,R4
003A 6480 XRL A,#080H
003C F8 MOV R0,A
003D EE MOV A,R6
003E 6480 XRL A,#080H
0040 98 SUBB A,R0
0041 50D1 JNC ?C0001[/mw_shl_code]
这个比较是成立的,tmp变量实现了加1。但是当比较值为如下的时候:
第二组数据:
[mw_shl_code=c,true]unsigned char xdata data1_L=0x03;
unsigned char xdata data1_H=0x6A;
unsigned char xdata data2_L=0x0A;
unsigned char xdata data2_H=0xFA;[/mw_shl_code]
C代码中的比较语句是不成的,也就是说,tmp没有加1。那段汇编代码的大意就是:
data1的LSB减去data2的LSB,标记借位CY。data1的MSB减去data2的MSB减去上一次减法的借位CY。
如果当前借位CY为0证明data1>=data2,CY为1证明data1<data2。
那么问题来了,
汇编代码中最后的两次异或运算有何用意?这两次异或运算直接导致第二组数据判断结果不正确! |