;*******************************************************************************
;* 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) 2021 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 ;-----------------------------------------------------------------------
                    #ListOff
                    #Uses     mcu.inc
                    #ListOn

;*******************************************************************************
; Macro to print a single ASCII character in RegA

putc                macro
                    call      PutChar
                    endm

                    #MapOff
#endif ;------------------------------------------------------------------------
?_OBJECT_?
;*******************************************************************************
; 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.

                    #spauto

PrintBig            proc
                    push
                    #ais

                    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

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

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

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

                    pula
                    dbnza     Loop@@              ;repeat for all digits

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

                    #psp

                    lda       sz@@,spx
                    psha      counter@@

                    clra
          #ifhcs
                    ldhx      .dividend@@,spx
          #else
                    psha
                    lda       .dividend@@,spx
                    ldx       .dividend@@+1,spx
                    tah
                    pula
          #endif
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
                    rtc

                    #sp
;*******************************************************************************
                    #Exit
;*******************************************************************************
                    @EndStats

                    #MapOn

                    #RAM

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

                    #ROM

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

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

;*******************************************************************************

                    #spauto

Start               proc
                    @rsp

                    clr       index
          ;-------------------------------------- ;test PrintBig
                    #ais
          #ifhcs
                    ldhx      Number@@+6
                    pshhx
                    ldhx      Number@@+4
                    pshhx
                    ldhx      Number@@+2
                    pshhx
                    ldhx      Number@@
                    pshhx
          #else
                    ldhx      #Number@@
                    @rep,|    8|lda 8-:loop,x|psha
          #endif
                    lda       #:ais               ;however many bytes were pushed
                    tsx
                    call      PrintBig
                    ais       #:ais

Done                bra       *                   ;Answer: 9223372036854775807

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

                    #sp

                    @vector   Vreset,Start

                    end       :s19crc