Convert binary to decimal, fast!

Basic and Machine Language

Moderator: Moderators

Post Reply
mercifier
Vic 20 Drifter
Posts: 23
Joined: Sun Jun 18, 2006 4:17 pm

Convert binary to decimal, fast!

Post by mercifier »

The decimal mode of the 6502 seems so rarely used that people have almost forgotten that it even exists. (As far as I know, no part of the VIC's operating system uses it.) But there's a quick and memory efficient way to convert large binary numbers to BCD using it.

Just roll out bit by bit from the binary number, and for each bit set, add the BCD power of two to an ackumulating BCD sum. For best speed, use a table of BCD powers of two. For good speed and saving memory, calculate the next BCD power of two by adding the current to itself. (For 32 bit numers, you would need a table of 32*5 bytes; 32 powers of two, 10 digits each.)

Code: Select all

bcdsize	= 5	;number of bytes to hold BCD number
		;(number of decimal digits / 2)
binsize	= 4	;number of bits / 8

	sei
	sed
	lda #$40
	sta vflag_Set	;zero page location

	;clear BCD power of 2 variable & BCD ackumulator:

	ldx #bcdsize
	lda #0
clr	sta bcdpow2-1.x
	sta bcdackum-1.x
	dex
	bne clr
	lda #1
	sta bcdpow2+bcdsize-1	;start with 2^0

loop
	;shift out next bit

	ldx #binsize
	bit vflag_set	;sets the overflow flag
	clc
shift	ror binnumber-1.x
	beq @zero
	clv	;overflow flag cleared if any byte was nonzero
zero	dex
	bne shift
	bcc noadd	;no adding this time?


	;add current BCD power of 2 to BCD ackumulator

	ldx #bcdsize
	clc
add	lda bcdpow2-1.x
	adc bcdackum-1.x
	sta bcdackum-1.x
	dex
	bne add

	clv	;overflow flag not reliable after BCD arithmetic
noadd	bvs exit

	;calculate next BCD power of 2

	clc
	ldx #bcdsize
double
	lda bcdpow2-1.x
	adc bcdpow2-1.x
	sta bcdpow2-1.x
	dex
	bne double
	beq loop
exit
	cld
	cli
	rts
Notes:

The interrupt flag has to be set whenever the decimal flag is set, or the interrupt routine will go nuts. Don't forget to clear the flag!

For faster loop execution, the BCD numbers are stored "backwards" compared to normal binary numbers, i.e. the most significant digits comes first, and the loop index counts backwards to avoid an CPX instruction (which would discard the carry).

You can easily increase the sizes of the numbers to very large ones. The execution time increases (almost) linearly with the number of bits/digits. Just make sure that the largest possible binary numer fits into the number of BCD pairs that you specify.

This method could easily be adopted to floating point numbers. When printing it to screen, just insert a period where appropriate.
Post Reply