16-Bit Decimal Printing

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

16-Bit Decimal Printing

Post by chysn »

I did a cursory search of the forum and didn't see anything like this, so I figured I'd contribute it. The goal was a non-BASIC PRTFIX ($DDCD) replacement that doesn't use as many zero-page locations. It also supports left padding to a specified number of places. It's probably much faster than PRTFIX, too. As written, it supports unsigned 16-bit numbers.

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
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: 16-Bit Decimal Printing

Post by Mike »

My table-based implementation of a TI$ clock in the border should give an interesting read. ;)
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: 16-Bit Decimal Printing

Post by chysn »

Mike wrote: Wed Aug 18, 2021 4:05 pm My table-based implementation of a TI$ clock in the border should give an interesting read. ;)
Hey, is that your first post?!

I did consider the "do subtraction and add back if negative" approach that you used instead of the "check for sufficiency before subtraction" approach. From a code size and cycles standpoint it seems pretty close to a wash, but my brain groks the division algorithm much more readily with the check up front. I think that's how I do it in my head.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: 16-Bit Decimal Printing

Post by Mike »

chysn wrote:Hey, is that your first post?!
Yep! :mrgreen:
I did consider the "do subtraction and add back if negative" approach that you used instead of the "check for sufficiency before subtraction" approach. From a code size and cycles standpoint it seems pretty close to a wash, but my brain groks the division algorithm much more readily with the check up front. I think that's how I do it in my head.
For my directory display routine in MINIPAINT, I used yet another method. For each line, it first converts the 16-bit block count into 3 bytes BCD (6 digits) with a routine originally devised by Andrew Jacobs (BitWise on 6502.org) and then inspects the BCD digits one-by-one, starting output with the first non-0 or last digit.

That directory routine as whole goes into some lengths to get its job done, but the output is printed into a 128x64 pixel bitmap (32x8 chars) overlaying the editor window, and cannot use standard KERNAL I/O.


Sadly, Andrew passed away this year due to COVID-19. R.I.P.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: 16-Bit Decimal Printing

Post by chysn »

Mike wrote: Wed Aug 18, 2021 11:09 pm Sadly, Andrew passed away this year due to COVID-19. R.I.P.
I read that, very sad.
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Re: 16-Bit Decimal Printing

Post by tlr »

My take:

Code: Select all

clone_bdcd:
	stx	dividend_zp
	sta	dividend_zp+1
	ldy	#0
cb_lp1:
; setup remainder
	lda	#0
	ldx	#16+1
	clc
;	bcc	div_skp1
	; fall thru
; divide loop
div_lp1:
	rol
; does it fit?
	cmp	#10
	bcc	div_skp1	;no... shift in
; C = 1
; yes... subtract
	sbc	#10
; C = 1
div_skp1:
	rol	dividend_zp
	rol	dividend_zp+1
	dex
	bne	div_lp1
; Acc = remainder
	ora	#$30
	pha
	iny
	lda	dividend_zp
	ora	dividend_zp+1
	bne	cb_lp1

; print the result in reverse
cb_lp2:
	pla
	jsr	$ffd2
	dey
	bne	cb_lp2

	rts
(adapted from my implementation used in superfluid)
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: 16-Bit Decimal Printing

Post by chysn »

tlr wrote: Thu Aug 19, 2021 10:17 am My take:
Very cool!
Post Reply