|
Hex to bcd转换的算法比较 作者[晓奇] --- 晓奇工作室---
C语言主程序部分 // 左移移位法作hex to bcd转换的算法程序,加上这一段调用演示,以察看运行结果 // 12M晶振时汇编算法运行时间大约为1339ns,C语言减法转换时间大约897ns // 不同的输入数据在C语言的减法转换时间略有不同,最大时间59999时为1231ns // 所以C语言的减法运算还是略快一些。 // http://www.xiao-qi.com/晓奇工作室收集整理,Keil C51下调试运行通过
#i nclude <reg51.h>
unsigned char bcdData[3]; unsigned int ihexs; unsigned char disp_buffer[5];
extern void hex_bcd(unsigned int iHex); // 声明外部函数 void hextobcd(unsigned int hexs,unsigned char j);
void main(void){ ihexs = 59999; hex_bcd(ihexs); hextobcd(ihexs,5); while(1); } /*************************** hex to bcd 转换程序 ***************************/ void hextobcd(unsigned int hexs,unsigned char j) {
unsigned int va; unsigned char i; va = 10000; //最大数级万位 for (i=j-1;i;i--) { disp_buffer[i] = 0; //目标数组清零 while ((hexs>=va)&&(va>9)) { hexs -= va; //减除数 disp_buffer[i]++; //商位加1 } va /= 10; //除数除10,指向低一位 } disp_buffer[0]=hexs; //最后个位数 }
汇编语言模块,建立另一个文件 NAME HEX_BCD ;************************************************************************* ; Hex to 压缩BCD码的转换(每4位代表一位bcd码) ; 输入Hex:R6R7 返回地址:bcdData ;*bcdData = BCD(R6R7) ; http://www.xiao-qi.com/晓奇工作室收集整理,Keil C51下调试运行通过 ;************************************************************************* ?PR?_HEX_BCD?HEX_BCD SEGMENT CODE ; 码段定义叙述,需要对本文件内的所有 ?PR?_BCD_ADJ?HEX_BCD SEGMENT CODE ; 码段定义叙述,需要对本文件内的所有 PUBLIC _HEX_BCD EXTRN DATA(bcdData)
RSEG ?PR?_HEX_BCD?HEX_BCD _HEX_BCD:CLR A ;目标数据清零初始化 MOV bcdData, A MOV bcdData+1, A MOV bcdData+2, A MOV R2, #15 ; 共进行15次循环移位运算 H_B0: MOV A, R7 ; 低8位 RLC A ; 大循环左移 MOV R7, A ; 回存 MOV A, R6 ; 高8位 RLC A ; 大循环左移 MOV R6, A ; 回存。至此已获得当前数据的最高位
MOV A, bcdData+2 ; 目标数最低8位 RLC A ; 移入原数据的最高位 ACALL _BCD_ADJ ; 压缩BCD码的十进制调整 MOV bcdData+2, A ; 存回 MOV A, bcdData+1 ; 目标数中间8位 RLC A ; 移入进位位 ACALL _BCD_ADJ ; 压缩BCD码的十进制调整 MOV bcdData+1, A ; 存回 MOV A, bcdData ; 目标数最高8位 RLC A ; 移入进位位 ACALL _BCD_ADJ ; 压缩BCD码的十进制调整 MOV bcdData, A ; 存回 DJNZ R2, H_B0 ; 继续下一轮循环
; 目标数据再左移一位,将原数据的最后一位放入,这样总共进行了16次循环移位 MOV A, R6 RLC A MOV A, bcdData+2 RLC A MOV bcdData+2, A MOV A, bcdData+1 RLC A MOV bcdData+1, A MOV A, bcdData RLC A MOV bcdData, A RET
;************************************************************************* ; 压缩BCD码的十进制调整,基本思路:逢十进一,在这里因为还保留着最后一次左 ; 移, 所以进位判别的0AH(0A0H)变成相对右移了一位的05H(050H), 而强迫进行进位 ; 的方法是加上一个数字3(左移一位后就是6)。程序保护PSW ; 输入返回均使用Acc累加器 ;************************************************************************* RSEG ?PR?_BCD_ADJ?HEX_BCD
_BCD_ADJ: PUSH PSW PUSH ACC CJNE A, #50H, $+3 ; 高4位。做一个比较产生状态标志 JC B1 ; 如果小于#50H, 不用进位处理 POP ACC ; 取原数据作修改 ADD A, #30H ; 加上#30h,留待下一轮左移时产生进位 PUSH ACC ; 存回原数据 B1: ANL A, #0FH ; 仅考虑低4位 CJNE A, #5, $+3 ; 做一个比较产生状态标志 JC B2 ; 如果小于#5H, 不用进位处理 POP ACC ; 取原数据作修改 ADD A, #3 ; 加上#3h,留待下一轮左移时产生进位 PUSH ACC ; 存回原数据 B2: POP ACC ; 恢复现场 POP PSW RET end /////////////////////////////////////////////////////////////////////////////////////////////////////////////// [nobody]?的快速算法,速度更快。 /////////////////////////////////////////////////////////////////////////////////////////////////////////////// ?PR?_HEX_BCD?HEX_BCD SEGMENT CODE PUBLIC _HEX_BCD RSEG ?PR?_HEX_BCD?HEX_BCD _HEX_BCD: CLR A ;BCD码初始化 MOV R3,A MOV R4,A MOV R5,A MOV R2,#10H ;转换双字节十六进制整数 HB3: MOV A,R7 ;从高端移出待转换数的一位到CY中 RLC A MOV R7,A MOV A,R6 RLC A MOV R6,A MOV A,R3 ;BCD码带进位自身相加,相当于乘2 ADDC A,R3 DA A ;十进制调整 MOV R3,A MOV A,R4 ADDC A,R4 DA A MOV R4,A MOV A,R5 ADDC A,R5 MOV R5,A ;双字节十六进制数的万位数不超过6,不用调整 DJNZ R2,HB3 ;处理完16bit mov a,r3 mov r7,a mov a,r4 mov r6,a mov r4,#0 RET end
调用方法: extern unsigned int hex_bcd(unsigned int iHex); /*声明外部函数*/ 或 extern unsigned long hex_bcd(unsigned int iHex); /*声明外部函数*/ 完整的keil C51工程文件下载 Copyright? 2001-2004, 晓奇工作室 E-Mail:info#xiao-qi.com
|