FormatULONG

Purpose: Generate a character string that is the decimal representation of the UNSIGNED LONG INTEGER value passed.
Optionally print and/or copy the string generated.
Assumes:   There is sufficient buffer space if copying is enabled (maximum 15 BYTEs, e.g., "4,294,967,294 ", NULL.)
Passed: R25:R24:R23:R22  ULONG ulValue value to be formatted
R21:R20 BYTE *   bPtrBuffer starting SRAM address at which to generate output; NULL omits copying
R18 BYTE bFlags option BITs BIT_FMT_COMMAS, BIT_FMT_POST_Sp, BIT_FMT_PRINT, and BIT_FMT_SIGNED.
Returns:   Nothing.
Alters: SREG (the FLAGs) and possibly the caller's buffer and/or the print buffer; all other Registers are preserved.
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

   LDI     R30, 0               ; Initialize the bFlags BYTE with no bits set
   LDI     R31, 7               ;  and the copy buffer pointer MSByte to 7
   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    ; When a string was passed but no value could
   RJMP    ALocal_Ret           ;  be parsed from it, just exit now

   MOV     R18, R30             ; Transfer the bFlags BYTE
   LDI     R30, 0               ; Either point R21:R20 to the SRAM buffer at
   MOVW    R20, R30             ;  0x0700 or set it to a NULL pointer
   CALL    AFormatULONG         ; Format R25:R24:R23:R22 with the options that
   SBRC    R18, BIT_FMT_PRINT   ;  were specified; print CR and LF afterward
   CALL    APrintNewLine        ;  only if printing was selected
Local_Ret:     RET              ; Label and instruction can go on the same line

SetOptions:
   LDI     R22, ','             ; If the string contains a comma, set the bit
   RCALL   ALocal_strchr        ;  in the bFlags to insert readability commas
   BREQ    ACheckForPostSpace
   ORI     R30, 1 << BIT_FMT_COMMAS

CheckForPostSpace:
   LDI     R22, '!'             ; If the string contains an exclamation mark,
   RCALL   ALocal_strchr        ;  set the bit to place a space after the last
   BREQ    ACheckForPrint       ;  digit
   ORI     R30, 1 << BIT_FMT_POST_Sp

CheckForPrint:
   LDI     R22, '+'             ; It the string contains a plus sign, set the
   RCALL   ALocal_strchr        ;  bit which will cause the finished string to
   BREQ    ACheckForCopy        ;  be printed
   ORI     R30, 1 << BIT_FMT_PRINT

CheckForCopy:
   LDI     R22, '-'             ; If the string passed contains a minus sign,
   RCALL   ALocal_strchr        ;  change the MSByte of the pointer to the
   BREQ    AOptions_Ret         ;  copy buffer to 0, making it a NULL pointer
   LDI     R31, 0
Options_Ret:
   RET

Local_strchr:                   ; Note: strchr() only changes R24, R25 & FLAGs
   MOVW    R24, R26             ; Point R25:R24 at the string passed
   JMP     Astrchr              ; See if the string contains that character
Test it:
m>DS+ 0x700 16   ; Buffer starts out cleared
SRAM contents:
0700:  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
m>@ 0x1000 0xABC +
2748
m>ds+ 0x700 16   ; Printed and the same string enbuffered:
SRAM contents:
0700:  32 37 34 38 00 00 00 00-00 00 00 00 00 00 00 00  2748............
m>@ 0x1000 0xBCD  +,
3,021
m>ds+- 0x700 16   ; Printed and copied, with the comma inserted:
0700:  33 2C 30 32 31 00 00 00-00 00 00 00 00 00 00 00  3,021...........
m>@ 0x1000 0x1234  +,-
4,660
m>ds-+ 0x700 16  ; The string was not copied; prior one retained:
0700:  33 2C 30 32 31 00 00 00-00 00 00 00 00 00 00 00  3,021...........
m>@ 0x1000    0x1234   ,!+
4,660
m>ds+- 0x700 16  ; This time enbuffered, with a space following:
0700:  34 2C 36 36 30 20 00 00-00 00 00 00 00 00 00 00  4,660 ..........
m>@ 0x1000   0xFFFF  ,!
m>ds+- 0x700 16  ; Printing was omitted, but copied into the buffer:
0700:  36 35 2C 35 33 35 20 00-00 00 00 00 00 00 00 00  65,535 .........
m>@ 0x1000 -1 +,!
4,294,967,295
m>ds-+ 0x700 16  ; Formatted and printed, but the '-' skipped copying:
0700:  36 35 2C 35 33 35 20 00-00 00 00 00 00 00 00 00  65,535 .........
m>@ 0x1000 0xFFFFFFFF +,!
4,294,967,295
m>ds+- 0x700 16  ; Same numeric value, but copied (and all other options):
0700:  34 2C 32 39 34 2C 39 36-37 2C 32 39 35 20 00 00  4,294,967,295 ..
m>                                                                                         
Notes: The StackAlloc50 System Function is used by this routine to create a local buffer, into which the string is written.
The formatted string is then copied, or printed, or both (or neither.)
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 BIT causes the string to be transferred into the COM1 serial port buffer.
The BIT_FMT_SIGNED BIT causes the Most Significant BIT in R25 to be checked, and if logic 1, causes the value to be output as a SIGNED LONG, with '-' sign leading.
A SIGNED LONG has the range of -2,147,483,648 = 0x80000000 to 0x7FFFFFFF = +2,147,483,647.
Negative signed values range from -2,147,483,648 = 0x80000000 to -1 = 0xFFFFFFFF.
Dropin: 
(setup
code)
;   Setup for the FormatULONG() call:
; Passed:  R25:R24:R23:R22 ULONG  ulValue to be formatted
;                  R21:R20 BYTE * bPtrBuffer pointer to the SRAM buffer or NULL
;                      R18 BYTE   bFlags (BIT_FMT_... COMMAS, POST_Sp, & PRINT)
; Returns: Nothing.
; Alters:  Only the FLAGs and the copy and/or print buffer(s) selected
Also see:   The FormatULONGHex, FormatWORD, and FormatCopyAndPrint System Functions.