• entries
17
28
• views
32,023

# Hex to Decimal (0-65535)

2,157 views

Continuing with my Hex to Decimal routines, I have written one for 16 bit numbers.

This routine is really geared toward a NES. The NES has no decimal mode. I think most of the time programmers will just break their scores out into multiple bytes (one for each digit), and then handle rollover cases for greater than 9, and less than 0.

Here we are dealing with the case where they do want to use just 2 bytes of ram to hold a score. The idea is to take 16 bit number and convert it back into the 5 temporary digits used for the score. The desired outcome is to be really quick (not spending 100's and 100's of cycles), while also not spending gobs and gobs of rom. Of course, a routine that is quick and short is desired in almost any situation.

My routine takes 263 bytes, and does the job in 156 to 168 cycles. Stats are below:

```;--------------------------------
;0-9999 conversion stats
;--------------------------------
;cycles          occurances
;156 - \$0860 -->  2,144
;157 - 0
;158 - 0
;159 - \$16C0 -->  5,824
;160 - 0
;161 - 0
;162 - \$07F0 -->  2,032
;163 - 0
;164 - 0
;165 - 0
;166 - 0
;167 - 0
;168 - 0
;average execution is 158.97 cycles
;--------------------------------
;0-65535 conversion stats
;--------------------------------
;cycles          occurances
;156 - \$1738 -->  5,944
;157 - 0
;158 - 0
;159 - \$9528 --> 38,184
;160 - 0
;161 - 0
;162 - \$2A30 --> 10,800
;163 - 0
;164 - 0
;165 - \$1F18 -->  7,960
;166 - 0
;167 - 0
;168 - \$0A58 -->  2,648
;average execution is 160.31 cycles```

I like it when the best case and worse case execution times are close together. Here 0-9999 conversion gets done in 156-162 cycles, and 0-65535 gets done in 156-168 cycles. Both are pretty good.

Finally the routine:

```CONVERT_TO_ASCII = 0
IF CONVERT_TO_ASCII
ASCII_OFFSET = \$30
ELSE
ASCII_OFFSET = \$00
ENDIF

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    #\$F0                  ;2  @5
lsr                          ;2  @7
lsr                          ;2  @9    carry is clear, shifting just 2 times instead of 4,
tay                          ;2  @11   since interlaced tables are used.
lda    hexHigh               ;3  @14
and    #\$0F                  ;2  @16
tax                          ;2  @18
lda    Times4096_High,Y      ;4  @22
sta    decTenThousands       ;3  @25
lda    Times4096_Low,Y       ;4  @29
sta    temp                  ;3  @36
lda    Times4096_Med,Y       ;4  @40
tay                          ;2  @46
lda    hexLow                ;3  @49
and    #\$F0                  ;2  @51
lsr                          ;2  @53
lsr                          ;2  @55
tax                          ;2  @57
tya                          ;2  @59
cpx    #13*4                 ;2  @61   times 4 due to interlaced table
cpx    #7*4                  ;2  @65
tay                          ;2  @69   medByte
lda    hexLow                ;3  @72
and    #\$0F                  ;2  @74
bcs    .sub100               ;2³ @83/84
cmp    #100                  ;2  @85
bcc    .skip1                ;2³ @87/88
.sub100:
sbc    #100                  ;2  @89
iny                          ;2  @91
.skip1:
cmp    #100                  ;2  @93
bcc    .skip2                ;2³ @95/96
sbc    #100                  ;2  @97
iny                          ;2  @99
.skip2:
lsr                          ;2  @101
tax                          ;2  @103
lda    ShiftedBcdTab,X       ;4  @107
tax                          ;2  @109
rol                          ;2  @111
and    #\$0F                  ;2  @113
IF CONVERT_TO_ASCII
ora    #ASCII_OFFSET         ;2
ENDIF
sta    decOnes               ;3  @116
txa                          ;2  @118
lsr                          ;2  @120
lsr                          ;2  @122
lsr                          ;2  @124
IF CONVERT_TO_ASCII
ora    #ASCII_OFFSET         ;2
ENDIF
sta    decTens               ;3  @127
tya                          ;2  @129
cmp    #100                  ;2  @131
bcc    .skip3                ;2³ @133/134
sbc    #100                  ;2  @135
inc    decTenThousands       ;5  @140
.skip3:
lsr                          ;2  @142
tay                          ;2  @144
lda    ShiftedBcdTab,Y       ;4  @148
tay                          ;2  @150
rol                          ;2  @152
and    #\$0F                  ;2  @154
IF CONVERT_TO_ASCII
ora    #ASCII_OFFSET         ;2
ENDIF
sta    decHundreds           ;3  @157
tya                          ;2  @159
lsr                          ;2  @161
lsr                          ;2  @163
lsr                          ;2  @165
IF CONVERT_TO_ASCII
ora    #ASCII_OFFSET         ;2
ENDIF
sta    decThousands          ;3  @168```

ASCII output can be built into the routine at a cost of 8 more bytes and 8 more cycles.

Test rom and source below. Note this rom is for the 2600, not the NES. The screen stays black for several seconds while it is running, and then a green passed screen appears.

There are no comments to display.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.