Converting byte to hex string

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Converting byte to hex string

Post by barrym95838 »

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: Select all

; 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:
u16out.JPG
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)
Post Reply