from Ron Kreymborg and Mike Keitz
[ed: rough guess is that about 2200 instructions will be executed]
see also:
;****************************************************************** ; ; Test program for 32-bit unsigned binary to BCD and BCD to ASCII. ; ;****************************************************************** title "32-bit binary to ascii" list p=pic16f84,r=dec,n=80,x=off,st=off include <p16f84.inc> errorlevel -302 ; no bank warnings errorlevel -305 ; no default dest warnings #define number 123456789 loadd macro local m,n,p p = number / 16777216 movlw p movwf bin m = (number - p * 16777216) / 65536 movlw m movwf bin+1 n = (number - p * 16777216 - m * 65536) / 256 movlw n movwf bin+2 movlw number - p * 16777216 - m * 65536 - n * 256 movwf bin+3 endm CBLOCK 0x0c bin:4 ; 32-bit binary number (unsigned) bcd:10 ; 10 BC digits or 10 ascii chars pti,pto ; pointers ii temp cnt ENDC loadd ; load test value <number> call b2bcd ; convert to 32-bit binary to 10 bcd call bcd2a ; convert 10 bcd to 10 ascii goto $ ;****************************************************************** ; Convert the 10 binary coded digits (5 bytes) starting at ; <bcd> into an ascii string also starting at <bcd>. Original ; bcd digits are lost. bcd2a movlw bcd+9 movwf pto ; destination pointer movlw bcd+4 movwf pti ; source pointer movlw 5 ; 5 bytes to process movwf cnt bcd2a1 movf pti,w ; get current input pointer movwf fsr decf pti,f ; prepare for next movf indf,w ; get 2 bcds movwf temp ; save for later movf pto,w ; get current output pointer movwf fsr decf pto,f ; prepare for next decf pto,f movf temp,w ; get digits back andlw 0x0f ; process lsd addlw "0" movwf indf ; to output decf fsr,f swapf temp,w ; process msd andlw 0x0f addlw "0" movwf indf ; to output decfsz cnt ; all digits? goto bcd2a1 return ; yes ;****************************************************************** ; Convert 32-bit binary number at <bin> into a bcd number ; at <bcd>. Uses Mike Keitz's procedure for handling bcd ; adjust; Modified Microchip AN526 for 32-bits. b2bcd movlw 32 ; 32-bits movwf ii ; make cycle counter clrf bcd ; clear result area clrf bcd+1 clrf bcd+2 clrf bcd+3 clrf bcd+4 b2bcd2 movlw bcd ; make pointer movwf fsr movlw 5 movwf cnt ; Mike's routine: b2bcd3 movlw 0x33 addwf indf,f ; add to both nybbles btfsc indf,3 ; test if low result > 7 andlw 0xf0 ; low result >7 so take the 3 out btfsc indf,7 ; test if high result > 7 andlw 0x0f ; high result > 7 so ok subwf indf,f ; any results <= 7, subtract back incf fsr,f ; point to next decfsz cnt goto b2bcd3 rlf bin+3,f ; get another bit rlf bin+2,f rlf bin+1,f rlf bin+0,f rlf bcd+4,f ; put it into bcd rlf bcd+3,f rlf bcd+2,f rlf bcd+1,f rlf bcd+0,f decfsz ii,f ; all done? goto b2bcd2 ; no, loop return ; yes end
Questions:
Interested:
Comments:
Note that this code as written only works with default radix of 10, otherwise the constants (123456789 and 32), get interpreted as hex numbers. Put a period in front (.123456789 and .32) to make it more idiot proof
Code:
BIN2DEC MOVLW 0XFF MOVWF BIN1 MOVLW 0X04 MOVWF BIN2 MOVLW 0XFF MOVWF BIN3 MOVLW 0X04 MOVWF BIN4 MOVLW .32 ; 32-BITS MOVWF II ; MAKE CYCLE COUNTER CLRF DIGIT1 CLRF DIGIT2 CLRF DIGIT3 CLRF DIGIT4 CLRF DIGIT5 B2BCD2 LFSR FSR0,DIGIT1 ; MAKE POINTER MOVLW .5 MOVWF CNT ; MIKE'S ROUTINE: B2BCD3 MOVLW 0X33 ADDWF INDF0,F ; ADD TO BOTH NYBBLES BTFSC INDF0,3 ; TEST IF LOW RESULT > 7 ANDLW 0XF0 ; LOW RESULT >7 SO TAKE THE 3 OUT BTFSC INDF0,7 ; TEST IF HIGH RESULT > 7 ANDLW 0X0F ; HIGH RESULT > 7 SO OK SUBWF INDF0,F ; ANY RESULTS <= 7, SUBTRACT BACK INCF FSR0L,F ; POINT TO NEXT DECFSZ CNT GOTO B2BCD3 RLCF BIN4,F ; GET ANOTHER BIT RLCF BIN3,F RLCF BIN2,F RLCF BIN1,F RLCF DIGIT5,F ; PUT IT INTO BCD RLCF DIGIT4,F RLCF DIGIT3,F RLCF DIGIT2,F RLCF DIGIT1,F DECFSZ II,F ; ALL DONE? GOTO B2BCD2 ; NO, LOOP RETLW .0 ; yes