Yes, I realize that Wozniak probably did it in twelve bytes.
Code: Select all
DEC_OP = $62 ; PrintDec Operand (2 bytes)
DEC_PAD_FL = $64 ; Decimal padding flag
CHROUT = $ffd2 ; KERNAL character out
CHR_PAD = " " ; Left padding character (0 for no padding)
* = $1800
; Print Decimal Number
; Left-padded by spaces
; X = Low Byte
; A = High Byte
; Y = Number of Decimal Places Minus 1 (0-4)
; Place overflow is not handled, so if you're wrong, you'll leave
; base 10 for something undefined. Overflow can be handled by watching X
; at print_pl, if you need to do that.
PrintDec: lsr DEC_PAD_FL ; Clear padding flag
stx DEC_OP ; Store operand
sta DEC_OP+1 ; ,,
-next: ldx #0 ; X is the number of subtractions per place
-loop: lda DEC_OP ; Is there enough of a remainder in the
cmp PlaceLow,y ; operand to perform the division?
lda DEC_OP+1 ; ,,
sbc PlaceHigh,y ; ,,
bcc print_pl ; If not, use 0 for this place
inx ; Perform 16-bit substractions from the
lda DEC_OP ; operand, counting the number of times
sec ; the place value was subtracted in X.
sbc PlaceLow,y ; This will be the place digit.
sta DEC_OP ; ,,
lda DEC_OP+1 ; ,,
sbc PlaceHigh,y ; ,,
sta DEC_OP+1 ; ,,
bcs loop ;
print_pl: txa ;
bne in_number ; If the number is nonzero, just print it
bit DEC_PAD_FL ; Has there been a nonzero value in this number?
bmi in_number ; If so, print this as a zero
cpy #0 ; Is this the ones place?
beq in_number ; If so, print the final zero
lda #CHR_PAD ; Print this one as padding
jmp dec_out ; If CHR_PAD=0, number will be flush left
in_number: sec ; When the first nonzero digit is printed,
ror DEC_PAD_FL ; set the padding flag to stop padding
clc ; Add "0" to the place digit for PETSCII
adc #"0" ; and print it with KERNAL call
dec_out: jsr CHROUT ; ,, (Y is safe from this)
dey ; Decrement place counter and continue
bpl next ; ,,
rts
; Decimal system place values for 16-bit numbers, from low to high
; 1, 10, 100, 1000, 10000
PlaceLow: .byte $01,$0a,$64,$e8,$10
PlaceHigh: .byte $00,$00,$00,$03,$27