;* Module    : PRINTBIG.SUB
;* Programmer: Tony Papadimitriou <tonyp@acm.org>
;* Purpose   : Print from 8-bit to 2048-bit (256-byte) integer to output device
;* Language  : Motorola/Freescale/NXP HC08/9S08 Assembly Language (aspisys.com/ASM8)
;* Status    : FREEWARE Copyright (c) 2016 by Tony Papadimitriou <tonyp@acm.org>
;* Original  : http://www.aspisys.com/code/hc08/printbig.html
;* Note(s)   : Use: #Include printbig.sub
;*           :
;*           : Output is sent by the user-supplied "putc" macro.
;*           :
;*           : putc can be made to write to any output device if you use an
;*           : "OutputDevice" control flag, so that the subroutine can send its
;*           : output to any device (e.g., LCD, SCI), depending on OutputDevice.
;*           :
;*           :?Number         long      123456789           ;somewhere in RAM
;*           :                ...
;*           :                ldhx      #?Number            ;HX -> RAM number
;*           :                lda       #4                  ;A = bytes in number
;*           :                call      PrintBig            ;print plain number
;*           :
;* History   : 10.05.13 v1.00 Original
;*           : 11.03.31       putc macro must be predefined by user
;*           : 11.04.21       Moved test code at EOF (for #EXIT optimization)
;*           :                Optimized SP => SPX where possible
;*           : 15.07.10       Optimized PrintBig LDH with LDHX [-2 bytes]
;*           :                Added HC08 compatibility

#ifmain ;-----------------------------------------------------------------------
                    #Uses     mcu.inc

; Macro to print a single ASCII character in RegA

putc                macro
                    call      PutChar

#endif ;------------------------------------------------------------------------
; Purpose: Print a variable-size number as decimal ASCII string
; Input  : HX -> RAM-based (eg., stack) number to display as ASCII string
;        : A = size of number in bytes
; Output : None
; Note(s): Leading zeros are suppressed.
;        : Enough stack is required to hold the result for the largest number.
;        : Original number is destroyed (zeroed), so you may need to copy it
;        : to some temp location first, and use the temp for passing it to this
;        : function.


PrintBig            proc

                    psha                          ;stacked first is the
                    clr       1,asp               ;ASCIZ terminator

NextDigit@@         psha      digit@@             ;room for next digit (right to left)

                    psha      sz@@                ;save size and dividend pointer
                    pshhx     .dividend@@

                    clr       digit@@,sp          ;initial remainder = 0
Loop@@              psha

                    lda       ,x                  ;get dividend digit

                    ldhx      digit@@,sp          ;get previous remainder into H
                    ldx       digit@@,sp          ;get previous remainder into X
                    txh                           ;and then into H
                    ldx       #10                 ;X = divisor (10)

                    thx                           ;put new remainder temporarily
                    stx       digit@@,sp          ;... into digit@@

                    sta       ,x                  ;save updated dividend digit
                    aix       #1                  ;HX -> next dividend digit

                    dbnza     Loop@@              ;repeat for all digits

                    lda       digit@@,spx         ;A = remainder
                    add       #'0'                ;convert to ASCII
                    sta       digit@@,spx         ;save next result byte (right to left)


                    lda       sz@@,spx
                    psha      counter@@

                    ldhx      .dividend@@,spx
                    lda       .dividend@@,spx
                    ldx       .dividend@@+1,spx
IsItZero@@          ora       ,x
                    aix       #1
                    dbnz      counter@@,sp,IsItZero@@
                    ais       #:psp

;                   tsta                          ;while dividend <> 0 ...
                    pull                          ;...(CCR not changed since ORA)
                    bne       NextDigit@@         ;... keep going

Print@@             pula                          ;get next ASCIZ char
                    cbeqa     #0,Done@@           ;on terminator, exit
                    @putc                         ;else, print digit
                    bra       Print@@

Done@@              pull




index               rmb       1
buffer              rmb       21                  ;long enough for 64-bit ASCIZ result


; This example PutChar instead of printing it simply stores results in Buffer

PutChar             proc
                    ldx       index
                    sta       buffer,x
                    inc       index
                    rtc                           ;(breakpoint here; see RegA in simulator)



Start               proc

                    clr       index

          ;--- test PrintBig

                    ldhx      Number@@+6
                    ldhx      Number@@+4
                    ldhx      Number@@+2
                    ldhx      Number@@
                    ldhx      #Number@@
                    @rep,|    8|lda 8-:loop,x|psha
                    lda       #:ais               ;however many bytes were pushed
                    call      PrintBig
                    ais       #:ais

Done                bra       *                   ;Answer: 9223372036854775807

Number@@            long      $7FFFFFFF,$FFFFFFFF ;decimal: 9223372036854775807


                    @vector   Vreset,Start

                    end       :s19crc