Code: Select all
hexLo ;Input number
hexHi
numDigits ;Number of digits to output, minus 1
decE ;Most significant output digit
decD
decC
decB
decA ;Least significant output digit
; Tables for digit addition
digE
.db 3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
digD
.db 2,6,8,4,2,1,0,0,0,0,0,0,0,0,0,0
digC
.db 7,3,1,0,0,0,5,2,1,0,0,0,0,0,0,0
digB
.db 6,8,9,9,4,2,1,5,2,6,3,1,0,0,0,0
digA
.db 7,3,1,5,7,3,1,5,7,3,1,5,7,3,1,0
lda #$00 ;Initialize output digits
sta decA
sta decB
sta decC
sta decD
sta decE
ldy #$10 ;Current bit
nextBit
dey ;Advance to next bit value in table
bmi exit ;Exit if we're out of bits to check
lsr hexHi ;Shift input right once
ror hexLo
bcc nextBit ;Don't add if bit is 0
lda decA ;Ones place
adc digA,y ;Carry is always set here, table compensates for it
cmp #$0A ;Did the digit overflow?
bcc skipA ;Don't subtract if it didn't, carry stays cleared
sbc #$0A ;Carry is already set, and remains set
skipA
sta decA
ldx numDigits ;Number of digits remaining
beq nextBit
lda decB ;Tens place
adc digB,y
cmp #$0A ;Did the digit overflow?
bcc skipB ;Don't subtract if it didn't, carry stays cleared
sbc #$0A ;Carry is already set, and remains set
skipB
sta decB
dex ;Number of digits remaining
beq nextBit
lda decC ;Hundreds place
adc digC,y
cmp #$0A ;Did the digit overflow?
bcc skipC ;Don't subtract if it didn't, carry stays cleared
sbc #$0A ;Carry is already set, and remains set
skipC
sta decC
dex ;Number of digits remaining
beq nextBit
lda decD ;Thousands place
adc digD,y
cmp #$0A ;Did the digit overflow?
bcc skipD ;Don't subtract if it didn't, carry stays cleared
sbc #$0A ;Carry is already set, and remains set
skipD
sta decD
dex ;Number of digits remaining
beq nextBit
lda decE ;Ten thousands place
adc digE,y ;This fifth digit will never overflow
sta decE ;so carry will always be clear
bcc nextBit ;Branch always
exit
If you know you'll never use this to output more than 4 digits, you can insert a check to see if the input value is >= $270F and skip to a routine which outputs "9999". If you do this, you can remove the first row and the leftmost two columns of the table (change ldy #$10 to ldy #$0e), and you can remove the decE part of the unrolled loop, applying the carry skip and branch always tricks to the decD part instead.