FormatWORD

Purpose: Generate a character string that is the decimal representation of the WORD (UNSIGNED SHORT INTEGER) value passed.
Optionally print and/or copy the string generated.
Assumes:  There is sufficient buffer space if copying is enabled (maximum size is 8 BYTEs, e.g., "65,535 ", NULL.)
Passed: R25:R24  WORD wValue value to be formatted
R23:R22 BYTE *   bPtrBuffer   starting SRAM address at which to generate output; NULL omits copying
R20 BYTE bFlags option BITs BIT_FMT_COMMAS, BIT_FMT_POST_Sp, and BIT_FMT_PRINT.
Returns: R25:R24 WORD wZero The value 0
R23:R22 WORD wValue the value to be formatted, the same as was passed in R25:R24
R21:R20 BYTE * bPtrBuffer the starting SRAM copy destination address, same as passed in R23:R22
R18 BYTE bFlags the bFlags BYTE bit values, same as those passed in R20
Alters: R18, R20 through R25, the FLAGs and possibly the caller's copy buffer and/or print buffer
Example:  
.ORG  0x1000
   ADIW    R26, 0               ; If 'X' is zero, the command line has nothing
   BREQ    ALocal_Ret           ;  to be checked, so just exit immediately

   RCALL   ASetOptions          ; Call the subroutine to set all the options
   MOVW    R24, R26             ; Set the string pointer one last time to
   CALL    AParseValue          ;  parse any value in it into R25:R24:R23:R22
   SBRS    R21, BIT_PV_VALID    ; If no value could be parsed from it, exit now
   RJMP    ALocal_Ret           ; Note that ParseValue() preserved R31:R30

   MOVW    R24, R22             ; Move the Low WORD, returned in R23:R22
   MOV     R20, R30             ; Transfer the bFlags BYTE to R20
   LDI     R30, 0               ; Either point R23:R22 to the SRAM buffer at
   MOVW    R22, R30             ;  0x0700 or set it to a NULL pointer
   CALL    AFormatWORD          ; Format R25:R24 with the specified options
   SBRC    R18, BIT_FMT_PRINT   ; Print a Carriage Return and Line Feed after
   CALL    APrintNewLine        ;  that, but only if printing was selected

Local_Ret:
   RET

SetOptions:
   LDI     R31, 7               ; Initialize R31:R30 to 0x0700, pointing to
   LDI     R30, 0               ;  the SRAM copy destination buffer to use
   MOV     R21, R31             ; Set the same value into R21 (the OR value)
   LDI     R22, '-'             ; If the string passed contains a minus sign,
   RCALL   ALocal_strchr        ;  zero the MSByte of the buffer pointer by
   SUB     R31, R30             ;  subtracting the same value set into R30

OtherOptions:
   LDI     R30, 0               ; Initialize the bFlags BYTE with no bits set
   LDI     R21, 1 << BIT_FMT_COMMAS
   LDI     R22, ','             ; If the string contains a comma, set the bit
   RCALL   ALocal_strchr        ;  in the bFlags to insert readability commas
   LDI     R21, 1 << BIT_FMT_POST_Sp
   LDI     R22, '!'             ; If the string contains an exclamation mark,
   RCALL   ALocal_strchr        ;  set the bit to place a space suffix
   LDI     R21, 1 << BIT_FMT_PRINT ; If the string contains a plus sign, set
   LDI     R22, '+'             ;  the bit which will print the string created

Local_strchr:                   ; Note: strchr() only changes R24, R25 & FLAGs
   MOVW    R24, R26             ; Point R25:R24 at the string passed
   CALL    Astrchr              ; See if the string contains that character
   BREQ    ALocal_Ret           ; If it does NOT, skip to a RET instruction
   OR      R30, R21             ; But if it does, combine the BIT into R30
   RET
Test it:
m>DS+ 0x700 16    ; Buffer is initially zeroed out
0700:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
m>@ 0x1000 50000 +-,
50,000
m>ds+- 0x700 16   ; Printed, with a comma, but not copied to the buffer
0700:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
m>@ 0x1000 40000 !-+
40000
m>ds+- 0x700 16   ; Printed, space suffix, no comma, not enbuffered
0700:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
m>@ 0x1000 54321 ,+!
54,321
m>DS-+ 0x700 16
0700:  35 34 2C 33 32 31 20 00-00 00 00 00 00 00 00 00  54,321 .........
m>ESL 0x700 = 0 0   ; Zero the first eight (8) BYTES of the buffer
m>DS+- 0x700 16
0700:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
m>@ 0x1000  0x10080  ,+!
128
m>ds+- 0x700 16   ; All bits over BYTE value 0xFFFF were discarded
0700:  31 32 38 20 00 00 00 00-00 00 00 00 00 00 00 00  128 ............
m>?, 0x10080      ; The actual ULONG value of 0x10080
65,664
m>?, 0x80         ; The value FormatWORD received and created
128
m>@ 0x1000 54321 ,!
m>DS+- 0x700 16   ; Enbuffered, not printed, CRLF line skipped
0700:  35 34 2C 33 32 31 20 00-00 00 00 00 00 00 00 00  54,321 .........
m>                                                                              
Notes: This routine uses the FormatULONG, which in turn uses the StackAlloc50 and FormatCopyAndPrint System Functions.
The BIT_FMT_COMMAS bit causes a comma to delimit the string at the expected three-digit intervals.
The BIT_FMT_POST_Sp bit pads a space character after the last numeric digit.
The BIT_FMT_PRINT causes the string to be transferred into the COM1 serial port buffer.
Dropin: 
(setup
code)
;   Setup for the FormatWORD() call:
; Passed:  R25:R24 WORD   wValue to be formatted
;          R23:R22 BYTE * bPtrBuffer pointer to the SRAM buffer or NULL
;              R20 BYTE   bFlags (BIT_FMT_... COMMAS, POST_Sp, & PRINT)
; Returns: R25:R24 WORD   
;          R23:R22 WORD   wValue to be formatted, same as the R25:R24 passed
;          R21:R20 BYTE * bPtrBuffer pointer, same as the R23:R22 passed
;              R18 BYTE   bFlags bits, same as the R20 passed
; Alters:  The Registers above, the FLAGs and the buffer(s) selected
Also see:  The FormatULONGHex, FormatULONG, FormatCopyAndPrint, PrintHexWORD, and Print0xHexWORD System Functions.