Here is a routine I wrote to convert a 16 bit number (0-65535) to decimal, each digit separated. It only takes 150 to 162 cycles as shown below.
Edit - This is now revision 2 of the code...
Here is the routine. It takes 258 bytes which is pretty good considering how fast it goes. There are other routines out there that are much shorter, but take 100's of cycles. My goal was speed while keeping the byte cost as low as possible.
If you want ASCII, then you can compile it in at a cost of just 8 more bytes, and 8 more cycles.
Edit - This is now revision 2 of the code...
Code:
;--------------------------------
;0-9999 conversion stats
;--------------------------------
;cycles occurances
;150 - $0860 --> 2,144
;151 - 0
;152 - 0
;153 - $16C0 --> 5,824
;154 - 0
;155 - 0
;156 - $07F0 --> 2,032
;average execution is 152.97 cycles
;--------------------------------
;0-65535 conversion stats
;--------------------------------
;cycles occurances
;150 - $1738 --> 5,944
;151 - 0
;152 - 0
;153 - $9528 --> 38,184
;154 - 0
;155 - 0
;156 - $2A30 --> 10,800
;157 - 0
;158 - 0
;159 - $1F18 --> 7,960
;160 - 0
;161 - 0
;162 - $0A58 --> 2,648
;average execution is 154.31 cycles
;0-9999 conversion stats
;--------------------------------
;cycles occurances
;150 - $0860 --> 2,144
;151 - 0
;152 - 0
;153 - $16C0 --> 5,824
;154 - 0
;155 - 0
;156 - $07F0 --> 2,032
;average execution is 152.97 cycles
;--------------------------------
;0-65535 conversion stats
;--------------------------------
;cycles occurances
;150 - $1738 --> 5,944
;151 - 0
;152 - 0
;153 - $9528 --> 38,184
;154 - 0
;155 - 0
;156 - $2A30 --> 10,800
;157 - 0
;158 - 0
;159 - $1F18 --> 7,960
;160 - 0
;161 - 0
;162 - $0A58 --> 2,648
;average execution is 154.31 cycles
Here is the routine. It takes 258 bytes which is pretty good considering how fast it goes. There are other routines out there that are much shorter, but take 100's of cycles. My goal was speed while keeping the byte cost as low as possible.
If you want ASCII, then you can compile it in at a cost of just 8 more bytes, and 8 more cycles.
Code:
;----------------------------------------------------------
;Convert 16 bit Hex to Decimal (0-65535) Rev 2
;By Omegamatrix
;Further optimizations by tepples
;
; Takes 150-162 cycles to execute.
;
; Starts with 16 bit number split into hexHigh and hexLow.
; Uses A,X,Y, and three bytes of zeropage ram:
;
; Ten Thousands digit - zp ram
; Thousands digit - returned in A register
; Hundreds digit - zp ram
; Tens digit - returned in X register
; Ones digit - zp ram
;----------------------------------------------------------
;temp register and decHundreds are doubled up to save ram...
temp = decHundreds
ASCII_OFFSET = $30
Times256_Low:
.byte $00,$38,$0C,$44,$18,$50,$24,$5C
.byte $30,$04,$3C,$10,$48,$1C,$54,$28
Times256_Med:
.byte $00,$02,$05,$07,$0A,$0C,$0F,$11
.byte $14,$17,$19,$1C,$1E,$21,$23,$26
Times16_Low:
.byte $00
Times4096_Low:
.byte $00
Times4096_Med:
.byte $00
Times4096_High:
.byte $00 + ASCII_OFFSET
.byte $10,$60,$28,$00 + ASCII_OFFSET ; interlaced tables, this allows less shifts to be made...
.byte $20,$5C,$51,$00 + ASCII_OFFSET
.byte $30,$58,$16,$01 + ASCII_OFFSET
.byte $40,$54,$3F,$01 + ASCII_OFFSET
.byte $50,$50,$04,$02 + ASCII_OFFSET
.byte $60,$4C,$2D,$02 + ASCII_OFFSET
.byte $0C,$48,$56,$02 + ASCII_OFFSET
.byte $1C,$44,$1B,$03 + ASCII_OFFSET
.byte $2C,$40,$44,$03 + ASCII_OFFSET
.byte $3C,$3C,$09,$04 + ASCII_OFFSET
.byte $4C,$38,$32,$04 + ASCII_OFFSET
.byte $5C,$34,$5B,$04 + ASCII_OFFSET
.byte $08,$30,$20,$05 + ASCII_OFFSET
.byte $18,$2C,$49,$05 + ASCII_OFFSET
.byte $28,$28,$0E,$06 + ASCII_OFFSET
ShiftedBcdTab
.byte $00,$01,$02,$03,$04,$08,$09,$0A,$0B,$0C
.byte $10,$11,$12,$13,$14,$18,$19,$1A,$1B,$1C
.byte $20,$21,$22,$23,$24,$28,$29,$2A,$2B,$2C
.byte $30,$31,$32,$33,$34,$38,$39,$3A,$3B,$3C
.byte $40,$41,$42,$43,$44,$48,$49,$4A,$4B,$4C
StartHexToDec:
lda hexHigh ;3 @3
and #$0F ;2 @5
tax ;2 @7
eor hexHigh ;3 @10
lsr ;2 @12 carry is clear, shifting just 2 times instead of 4,
lsr ;2 @14 since interlaced tables are used.
tay ;2 @16
lda Times4096_High,Y ;4 @20
sta decTenThousands ;3 @23
lda Times4096_Low,Y ;4 @27
adc Times256_Low,X ;4 @31
sta temp ;3 @34
lda Times4096_Med,Y ;4 @38
adc Times256_Med,X ;4 @42
tay ;2 @44
lda hexLow ;3 @47
and #$F0 ;2 @49
lsr ;2 @51
lsr ;2 @53
tax ;2 @55
tya ;2 @57
cpx #13*4 ;2 @59 times 4 due to interlaced table
adc #0 ;2 @61
cpx #7*4 ;2 @63
adc #0 ;2 @65
tay ;2 @67
lda hexLow ;3 @70
and #$0F ;2 @72
adc Times16_Low,X ;4 @76
adc temp ;3 @79
bcs .sub100 ;2³ @81/82
cmp #100 ;2 @83
bcc .skip1 ;2³ @85/86
.sub100:
sbc #100 ;2 @87
iny ;2 @89
.skip1:
cmp #100 ;2 @91
bcc .skip2 ;2³ @93/94
sbc #100 ;2 @95
iny ;2 @97
.skip2:
lsr ;2 @99
tax ;2 @101
lda ShiftedBcdTab,X ;4 @105
tax ;2 @107
rol ;2 @109
and #$0F ;2 @111
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
sta decOnes ;3 @114
txa ;2 @116
lsr ;2 @118
lsr ;2 @120
lsr ;2 @122
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
tax ;2 @124 or STA decTens
tya ;2 @126
cmp #100 ;2 @128
bcc .skip3 ;2³ @130/131
sbc #100 ;2 @132
inc decTenThousands ;5 @137
.skip3:
lsr ;2 @139
tay ;2 @141
lda ShiftedBcdTab,Y ;4 @145
tay ;2 @147
rol ;2 @149
and #$0F ;2 @151
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
sta decHundreds ;3 @154
tya ;2 @156
lsr ;2 @158
lsr ;2 @160
lsr ;2 @162
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
; A = decThousands
;Convert 16 bit Hex to Decimal (0-65535) Rev 2
;By Omegamatrix
;Further optimizations by tepples
;
; Takes 150-162 cycles to execute.
;
; Starts with 16 bit number split into hexHigh and hexLow.
; Uses A,X,Y, and three bytes of zeropage ram:
;
; Ten Thousands digit - zp ram
; Thousands digit - returned in A register
; Hundreds digit - zp ram
; Tens digit - returned in X register
; Ones digit - zp ram
;----------------------------------------------------------
;temp register and decHundreds are doubled up to save ram...
temp = decHundreds
ASCII_OFFSET = $30
Times256_Low:
.byte $00,$38,$0C,$44,$18,$50,$24,$5C
.byte $30,$04,$3C,$10,$48,$1C,$54,$28
Times256_Med:
.byte $00,$02,$05,$07,$0A,$0C,$0F,$11
.byte $14,$17,$19,$1C,$1E,$21,$23,$26
Times16_Low:
.byte $00
Times4096_Low:
.byte $00
Times4096_Med:
.byte $00
Times4096_High:
.byte $00 + ASCII_OFFSET
.byte $10,$60,$28,$00 + ASCII_OFFSET ; interlaced tables, this allows less shifts to be made...
.byte $20,$5C,$51,$00 + ASCII_OFFSET
.byte $30,$58,$16,$01 + ASCII_OFFSET
.byte $40,$54,$3F,$01 + ASCII_OFFSET
.byte $50,$50,$04,$02 + ASCII_OFFSET
.byte $60,$4C,$2D,$02 + ASCII_OFFSET
.byte $0C,$48,$56,$02 + ASCII_OFFSET
.byte $1C,$44,$1B,$03 + ASCII_OFFSET
.byte $2C,$40,$44,$03 + ASCII_OFFSET
.byte $3C,$3C,$09,$04 + ASCII_OFFSET
.byte $4C,$38,$32,$04 + ASCII_OFFSET
.byte $5C,$34,$5B,$04 + ASCII_OFFSET
.byte $08,$30,$20,$05 + ASCII_OFFSET
.byte $18,$2C,$49,$05 + ASCII_OFFSET
.byte $28,$28,$0E,$06 + ASCII_OFFSET
ShiftedBcdTab
.byte $00,$01,$02,$03,$04,$08,$09,$0A,$0B,$0C
.byte $10,$11,$12,$13,$14,$18,$19,$1A,$1B,$1C
.byte $20,$21,$22,$23,$24,$28,$29,$2A,$2B,$2C
.byte $30,$31,$32,$33,$34,$38,$39,$3A,$3B,$3C
.byte $40,$41,$42,$43,$44,$48,$49,$4A,$4B,$4C
StartHexToDec:
lda hexHigh ;3 @3
and #$0F ;2 @5
tax ;2 @7
eor hexHigh ;3 @10
lsr ;2 @12 carry is clear, shifting just 2 times instead of 4,
lsr ;2 @14 since interlaced tables are used.
tay ;2 @16
lda Times4096_High,Y ;4 @20
sta decTenThousands ;3 @23
lda Times4096_Low,Y ;4 @27
adc Times256_Low,X ;4 @31
sta temp ;3 @34
lda Times4096_Med,Y ;4 @38
adc Times256_Med,X ;4 @42
tay ;2 @44
lda hexLow ;3 @47
and #$F0 ;2 @49
lsr ;2 @51
lsr ;2 @53
tax ;2 @55
tya ;2 @57
cpx #13*4 ;2 @59 times 4 due to interlaced table
adc #0 ;2 @61
cpx #7*4 ;2 @63
adc #0 ;2 @65
tay ;2 @67
lda hexLow ;3 @70
and #$0F ;2 @72
adc Times16_Low,X ;4 @76
adc temp ;3 @79
bcs .sub100 ;2³ @81/82
cmp #100 ;2 @83
bcc .skip1 ;2³ @85/86
.sub100:
sbc #100 ;2 @87
iny ;2 @89
.skip1:
cmp #100 ;2 @91
bcc .skip2 ;2³ @93/94
sbc #100 ;2 @95
iny ;2 @97
.skip2:
lsr ;2 @99
tax ;2 @101
lda ShiftedBcdTab,X ;4 @105
tax ;2 @107
rol ;2 @109
and #$0F ;2 @111
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
sta decOnes ;3 @114
txa ;2 @116
lsr ;2 @118
lsr ;2 @120
lsr ;2 @122
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
tax ;2 @124 or STA decTens
tya ;2 @126
cmp #100 ;2 @128
bcc .skip3 ;2³ @130/131
sbc #100 ;2 @132
inc decTenThousands ;5 @137
.skip3:
lsr ;2 @139
tay ;2 @141
lda ShiftedBcdTab,Y ;4 @145
tay ;2 @147
rol ;2 @149
and #$0F ;2 @151
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
sta decHundreds ;3 @154
tya ;2 @156
lsr ;2 @158
lsr ;2 @160
lsr ;2 @162
IF ASCII_OFFSET
ora #ASCII_OFFSET ;2
ENDIF
; A = decThousands