User Tools

Site Tools


base:more_hexadecimal_to_decimal_conversion

More Hexadecimal to Decimal Conversion

These are equivalent routines to Garth Wilson's Hexadecimal to Decimal routines, eliminating the lookup tables in exchange for a little slower execution speed. A discussion of hexadecimal-to-decimal routines can be found in this thread on the 6502.org Forum.

First is the 8-bit version. Start with the input number in accumulator:

; Convert an 8 bit binary value to BCD
;
; This function converts an 8 bit binary value into a 16 bit BCD. It
; works by transferring one bit a time from the source and adding it
; into a BCD value that is being doubled on each iteration. As all the
; arithmetic is being done in BCD the result is a binary to decimal
; conversion.  All conversions take 311 clock cycles.
;
; For example the conversion of a $96 would look like this:
;
; BIN = $96 -> BIN' = $2C C = 1 | BCD $0000 x2 + C -> BCD' $0001
; BIN = $2C -> BIN' = $58 C = 0 | BCD $0001 x2 + C -> BCD' $0002
; BIN = $58 -> BIN' = $B0 C = 0 | BCD $0002 x2 + C -> BCD' $0004
; BIN = $B0 -> BIN' = $60 C = 1 | BCD $0004 x2 + C -> BCD' $0009
; BIN = $60 -> BIN' = $C0 C = 0 | BCD $0009 x2 + C -> BCD' $0018
; BIN = $C0 -> BIN' = $80 C = 1 | BCD $0018 x2 + C -> BCD' $0037
; BIN = $80 -> BIN' = $00 C = 1 | BCD $0037 x2 + C -> BCD' $0075
; BIN = $00 -> BIN' = $00 C = 0 | BCD $0075 x2 + C -> BCD' $0150
;
; This technique is very similar to Garth Wilsons, but does away with
; the look up table for powers of two and much simpler than the approach
; used by Lance Leventhal in his books (e.g. subtracting out 1000s, 100s,
; 10s and 1s).
;
; Andrew Jacobs, 28-Feb-2004

		.ORG $0200

BINBCD8:	SED		; Switch to decimal mode
		LDA #0		; Ensure the result is clear
		STA BCD+0
		STA BCD+1
		LDX #8		; The number of source bits
		
CNVBIT:		ASL BIN		; Shift out one bit
		LDA BCD+0	; And add into result
		ADC BCD+0
		STA BCD+0
		LDA BCD+1	; propagating any carry
		ADC BCD+1
		STA BCD+1
		DEX		; And repeat for next bit
		BNE CNVBIT
		CLD		; Back to binary
		
		BRK		; All Done.
		
; A test value to be converted

		.ORG $0300
		
BIN		.DB  234
BCD		.DS  2

Here a stripped down version to compute a BCD number not larger than 99 (single byte). You send and receive the value in A. The intermediate variables are in page zero.

; Convert a 7 bit binary value to BCD
;
; This routine converts a binary value to BCD; the value cannot be larger than 99.
; Same working principle of the other routines.
; The value to convert is sent in A, and the result will be in A. X value is destroyed.
; The routine executes in 124 cycles (+rts). 
;
; Verz!!! 18-Mar-2017

BinBcd_sb	ldx #$7		; The number of source bits     2c
		asl 		;				2c
;		ldx #$6	; you can replace the  LDX#$7/ASL with LDX#$6/ASL/ASL
;		asl	; to compute values up to 63 (as for a clock)
;		asl
		sta <bin	;				3c
		lda #$0		; Ensure the result is clear    2c
		sed		; Switch to decimal mode	2c
CnvBit_sb	asl <BIN	; Shift out one bit		5c |
		sta <BCD0	;				3c |
		adc <BCD0	;				3c | 16c
		dex		; And repeat for next bit	2c |
		bne CnvBit_sb	;				3c |
		cld		; Back to binary		2c
		rts  		; All Done.

BIN	.equ  $fc
BCD0	.equ  $fb

Here is an equivalent routine for converting 16-bit numbers:

; Convert an 16 bit binary value to BCD
;
; This function converts a 16 bit binary value into a 24 bit BCD. It
; works by transferring one bit a time from the source and adding it
; into a BCD value that is being doubled on each iteration. As all the
; arithmetic is being done in BCD the result is a binary to decimal
; conversion. All conversions take 915 clock cycles.
;
; See BINBCD8 for more details of its operation.
;
; Andrew Jacobs, 28-Feb-2004

		.ORG $0200

BINBCD16:	SED		; Switch to decimal mode
		LDA #0		; Ensure the result is clear
		STA BCD+0
		STA BCD+1
		STA BCD+2
		LDX #16		; The number of source bits
		
CNVBIT:		ASL BIN+0	; Shift out one bit
		ROL BIN+1
		LDA BCD+0	; And add into result
		ADC BCD+0
		STA BCD+0
		LDA BCD+1	; propagating any carry
		ADC BCD+1
		STA BCD+1
		LDA BCD+2	; ... thru whole result
		ADC BCD+2
		STA BCD+2
		DEX		; And repeat for next bit
		BNE CNVBIT
		CLD		; Back to binary
		
		BRK		; All Done.
		
; A test value to be converted

		.ORG $0300
		
BIN		.DW  12345
BCD		.DS  3

This is the same routine, just unrolled. It gains 250 cycles for that (30%). Using zero page variables the gain is of 116 cycles more.

;-------------------------------
; Converts a 16bit number in BCD
;-------------------------------
;
;  call it with the value in bin
;-------------------------------
BINBCD16
        SED             ; Switch to decimal mode        2
        LDA #0          ; Ensure the result is clear    2
        STA bcd+0;                                      4
        STA bcd+1;                                      4
        STA bcd+2;                                      4       16
 
        LDX #6;                                         2       2
CNVBIT1          
        ASL bin+0       ; Shift out one bit             6
        ROL bin+1       ;                               6
;        LDA bcd+0      ; And add into result          
        ADC bcd+0       ;                               4
        STA bcd+0       ;                               4
;        LDA bcd+1      ; propagating any carry
;        ADC bcd+1
;        STA bcd+1
;        LDA bcd+2      ; ... thru whole result
;        ADC bcd+2
;        STA bcd+2
        DEX             ; And repeat for next bit       2
        BNE CNVBIT1     ;                               3       25*6-1=149
 
        LDX #7;                                         2       2
CNVBIT2
        ASL bin+0      ; Shift out one bit              6
        ROL bin+1       ;                               6
        LDA bcd+0      ; And add into result            4
        ADC bcd+0       ;                               4
        STA bcd+0       ;                               4
        LDA bcd+1      ; propagating any carry          4
        ADC bcd+1       ;                               4
        STA bcd+1       ;                               4
;        LDA bcd+2      ; ... thru whole result
;        ADC bcd+2
;        STA bcd+2
        DEX             ; And repeat for next bit       2
        BNE CNVBIT2     ;                               3       41*7-1=286
 
        LDX #3;                                         2       2
CNVBIT3
        ASL bin+0       ; Shift out one bit             6
        ROL bin+1       ;                               6
        LDA bcd+0      ; And add into result            4
        ADC bcd+0       ;                               4
        STA bcd+0       ;                               4
        LDA bcd+1      ; propagating any carry          4
        ADC bcd+1       ;                               4
        STA bcd+1       ;                               4
        LDA bcd+2      ; ... thru whole result          4
        ADC bcd+2       ;                               4
        STA bcd+2       ;                               4
        DEX             ; And repeat for next bit       2
        BNE CNVBIT3     ;                               3       53*3-1=158
 
        CLD             ; Back to binary                2       2; tot 615
       
        rts             ; All Done.                            
base/more_hexadecimal_to_decimal_conversion.txt · Last modified: 2019-08-16 01:44 by verz