6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 1:05 am

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Fri Aug 10, 2018 4:22 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
I have been playing around with some 8-bit ideas to settle my brain among the daily chaos, and recently arrived at this little ditty, in the key of NMOS:
Code:
; u16out:  Print a 16-bit unsigned integer to stdout by
;   Michael T. Barry 2018.07.31.  Free to copy, use and
;   modify, but with NO warranty of any kind whatsoever.
; Credit and thanks to John Brooks for inspiring the
;   V-flag and "loaded rts" tricks.  57 bytes.
; Entry:  X reg points to a zp data frame containing:
;         0,x  LSB of unsigned integer to print
;         1,x  MSB       "        "         "
;         2,x  radix of conversion (2,4,6, .. ,34,36)
;              digits above '9' come from ('A' .. 'Z')
;         3,x  minimum output field_width (three bytes of
;              stack are used for each char output, so
;              wide fields should be used with caution)
;         4,x  pad_char to be added to the left of the
;              output to achieve the minimum field_width
;              (this parameter is only used if padding is
;              required, and unlike the above paramenters
;              is not trashed by this subroutine, making
;              it optional)
; Exit:   X contents are preserved
;         A, Y & data frame contents are NOT preserved
; Uses 3*(field_width)+2 bytes of the system return stack
      .or   f00         ;
u16out:                 ; our optimized in-line divmod
      lsr   2,x         ;   prefers to work with radix/2
      dec   3,x         ; at least one digit will be output
u16outa:                ; repeat {
      lda   #0          ;   initialize 8-bit remainder
      bit   u16oute     ;   set V (quotient==0 flag)
      ldy   #16         ;   prepare 16-bit/8-bit divmod
u16outb:                ;   repeat {
      cmp   2,x         ;     partial remainder >= radix/2?
      bcc   u16outc     ;     no: proceed
      sbc   2,x         ;     yes: update partial remainder
u16outc:                ;       CS, VC (quotient != 0)
      rol   0,x         ;     the new quotient gradually
      rol   1,x         ;       replaces the dividend
      rol               ;     A is gradually replaced with
      dey               ;       the new remainder
      bne   u16outb     ;   } until divmod is completed
      php               ;   save V flag
      cmp   #10         ;   digit > 9?
      bcc   u16outd     ;
      adc   #6          ;   yes: offset to upper case ALPHA
u16outd:                ;
      adc   #'0'        ;   translate digit to ASCII
      plp               ;   restore V flag
u16oute:                ;
      pha               ;   stack the digit (or pad char)
      lda   #>u16outf   ;
      pha               ;   stack the (address-1) of the
      lda   #<u16outf   ;     output routine to retrieve
      pha               ;     the char and print it
      dec   3,x         ;   update the field width counter
      bvc   u16outa     ; } until the quotient is 0
      bmi   u16outf     ; need any pad_chars for left side?
      lda   4,x         ; yes:  prepare pad char and loop
      bvs   u16oute     ; (always)
u16outf:                ; this rts is "pre-loaded" to print
      rts               ;   all the digits in reverse order
      pla               ; retrieve digit
      jmp   cout        ; print it and proceed
      .en               ;

It's a subroutine that tests a few ideas about parameter passing and return stack trickery, with the added bonus that it prints any unsigned 16-bit integer to stdout in any even base from 2 to 36, with optional minimum field width and pad character parameters. Here's a peek at some example runs:

Attachment:
u16out.JPG
u16out.JPG [ 49.7 KiB | Viewed 1884 times ]


It is no speed demon, but packs all of this general-purpose functionality into only 57 bytes. I tried to provide adequate comments, but I can answer any questions you might have about the details. Critiques and suggestions for further optimization are also most welcome.

Please enjoy!

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron