;-------------------------------------------------------------------------- ; BIN24BCD.ASM ; ; Fast 24-bit binary to packed BCD conversion for AVC51_3 ; Small model. ; ; 990822 AdM initial version ;-------------------------------------------------------------------------- global stack_internal defseg c_text,class=CODE seg c_text _R equ 0 ; register bank 0 ;-------------------------------------------------------------------------- ; unsigned long bin24bcd( unsigned long bin) ; ; Convert 24 bits to 8 digits packed bcd. ; ; On entry, ?_bin24bcd+0...3 holds binary value (MSB..LSB). ; The lower 24 bits get stored into R0-1-6. ; On exit, R4-5-6-7 holds packed BCD (MSB...LSB). ; ; Algorithm: ; When the BIN value is leftshifted into the BCD result, each bit that ; would crossover into a higher nibble is really 16, so the BCD result ; is then corrected by adding 6 to the lower nibble. Also, nibbles above 9 ; are corrected by subtracting 10 from the lower nibble and adding 1 ; to the higher one (this is faster if we just add '6', the two's ; complement of 10, to the byte). ; ; Here it is even faster because we add 3 to the lower nibble BEFORE the ; shift, if the result then is > 7 a transfer of the highest bit to the ; next nibble would occur after the shift, so the transfer and the adding ; of 6 would be OK after the shift (6 = 3<<1). If not, the nibble is ; preserved by subtracting 3 again. Each nibble will never be > 9 so the ; checks for nibble values > 9 need not be made. ; ; Algorithm by Alexander Eisen, Electronic Design March 18 1996. ; Converted to Avocet C51 by Arie de Muijnck. ; ; Speed: about 1900 cycles (normally: printf("%8lu",..) takes 25700 cycles!) ;-------------------------------------------------------------------------- global _bin24bcd ; setup signatures for linker signat _bin24bcd,4220 ; including call graph info fnsize _bin24bcd,0,4 global ?_bin24bcd ; param _bin assigned to ?_bin24bcd+0..3 db ?_bin24bcd ; WHY? For compiler/linker... _bin24bcd: mov a, ?_bin24bcd ; get MSB jz do24 ; if > 24 bits (0..16777215) mov r2, #99h ; return 99999999 mov r3, #99h mov r4, #99h mov r5, #99h ret do24: mov r0, ?_bin24bcd+1 ; move lower 24 bits to R 0-1-6 (MSB..LSB) mov r1, ?_bin24bcd+2 mov r6, ?_bin24bcd+3 clr cy ; prepare shifting mov r2, #0 ; BCD = 00000000 mov r3, #0 mov r4, #0 mov r5, #0 mov b, #24 ; bits = 24 shloop: ; do xch a, r6 ; shift left BIN into BCD, 1 bit rlc a ; R2345 <-- R016 <-- 0 xch a, r6 xch a, r1 rlc a xch a, r1 xch a, r0 rlc a xch a, r0 xch a, r5 rlc a xch a, r5 xch a, r4 rlc a xch a, r4 xch a, r3 rlc a xch a, r3 xch a, r2 rlc a xch a, r2 djnz b, next ; if (--bits == 0) ret ; return BCD in R4567 next: mov a, r5 ; get two LSB nibbles of BCD call adj_bcd ; adjust them mov r5, a mov a, r4 ; same for others call adj_bcd mov r4, a mov a, r3 call adj_bcd mov r3, a mov a, r2 call adj_bcd mov r2, a sjmp shloop ; while (1) ;----- sub. adjust both BCD nibbles adj_bcd: add a, #03h ; adjust low nibble jb acc.3, lo ; if > 7 add a, #256-03h ; restore lo: add a, #30h ; adjust hi nibble jb acc.7, hi ; if > 127 add a, #256-30h ; restore hi: ret ;-------------------------------- eof ------------------------------------- end