NegateLONG

Purpose: Form the negative of a LONG INTEGER value.
Assumes:   Nothing.
Passed: R25:R24:R23:R22  LONG  mOriginal   the LONG INTEGER to be negated
Returns: R25:R24:R23:R22LONG  mNegative   the two's complement of the value passed
NFLAGBIT_N the sign of the value returned; TRUE if negative, FALSE if positive
Alters: Only the Registers returned and the FLAGs (SREG)
Example:  
.ORG   0x1000

DemonstrateNegate:
   ADIW    R26, 0                   ; If no parameter was passed in the command
   BREQ    ADemo_Ret                ;   line tail, just exit immediately
   MOVW    R24, R26                 ; Point to the buffer and parse any value
   CALL    AParseValue              ;  string which it contains; none illegal
   RCALL   ASavetoXandZ             ; Save the original in R31:R30:R27:R26
   RCALL   ADisplayValue            ; Show original value in both decimal and
   RCALL   ARestoreFromXandZ        ;  hexadecimal, then restore the original
   CALL    ANegateLONG              ;  value, then negate it and save it
   RCALL   ASavetoXandZ             ; Line 2: the negated results, again in
   RCALL   ADisplayValue            ;  both decimal and hexadecimal formats
   RCALL   ARestoreFromXandZ        ; Restore the saved negated value then
   CALL    ANegateLONG              ;  negate it again, save the results and
   RCALL   ASavetoXandZ             ;  print both decimal and hex for Line 3
;  RJMP    ADisplayValue            ; No need to call; just fall through

DisplayValue:
   RCALL   ASetupForFormatCALL      ; The common setup portion
   CALL    AFormatULONGHex          ; Output the value in hexadecimal format
   LDI     R25, 0x3A                ; ACSZ_SpaceEqualSpace is found at FLASH
   LDI     R24, 0xD2                ;  address 0x3AD2, which is " = "
   CALL    APrintFLASHASCIIz        ; Print the " = " string
   RCALL   ARestoreFromXandZ        ; R24 and R25 were trashed, so restore all
   RCALL   ASetupForFormatCALL
   CALL    AFormatULONG             ; Output the same value in decimal format
   JMP     APrintNewLine            ;  and finish each set with CR, LF

BITSET = (1 << BIT_FMT_PRE_0x) | (1 << BIT_FMT_PRINT) | (1 << BIT_FMT_COMMAS)

SetupForFormatCALL:
   LDI     R21, 0                   ; Set R21:R20 to a NULL pointer (no copy)
   LDI     R20, 0                   ; FormatULONGHex ignores BIT_FMT_COMMAS
   LDI     R18, BITSET              ; FormatULONG    ignores BIT_FMT_PRE_0x
Demo_Ret:
   RET

SavetoXandZ:
   MOVW    R30, R24                 ; Copy R25:R24:R23:R22 to R31:R30:R27:R26
   MOVW    R26, R22
   RET

RestoreFromXandZ:
   MOVW    R24, R30                 ; Copy R31:R30:R27:R26 to R25:R24:R23:R22
   MOVW    R22, R26
   RET
Test it:
m>@ 0x1000
m>@ 0x1000   0    ; Well, this makes sense, doesn't it?
0x0 = 0
0x0 = 0
0x0 = 0
m>                ; Output 3 lines for each: original, negated, re-negated
m>@ 0x1000  1
0x1 = 1
0xFFFFFFFF = 4,294,967,295
0x1 = 1
m>@ 0x1000 -42
0xFFFFFFD6 = 4,294,967,254
0x2A = 42
0xFFFFFFD6 = 4,294,967,254
m>@ 0x1000 0xABCDEF
0xABCDEF = 11,259,375
0xFF543211 = 4,283,707,921
0xABCDEF = 11,259,375
m>
m>@ 4096 2147483647
0x7FFFFFFF = 2,147,483,647
0x80000001 = 2,147,483,649
0x7FFFFFFF = 2,147,483,647
m>@ 4096 -2147483648        ; The only value with no negated (positive) version
0x80000000 = 2,147,483,648
0x80000000 = 2,147,483,648
0x80000000 = 2,147,483,648
m>@ 4096 -2147483647	
0x80000001 = 2,147,483,649
0x7FFFFFFF = 2,147,483,647
0x80000001 = 2,147,483,649
m>                                                                                         
Notes:By negation, what is meant is the binary pattern, which when added to the original, sums to zero. An additional aspect is that when negated again, the original value results (duh!) This is the two's complement.
With signed binary values, the Most Significant BIT (MSBit) is the treated as the "sign" bit. If it is zero (0), it's a positive number; if it is one (1), it's a negative number.
Negation is needed to simplify the division routines.
Dropin: 
(setup
code)
;   Setup for the NegateLONG() call:
; Passed:  R25:R24:R23:R22 LONG mOriginal the 32-BIT (4-BYTE) signed value
; Returns: R25:R24:R23:R22 LONG mNegative the 32-BIT (4-BYTE) negative of it
;                        N FLAG BIT_N sign of return value; TRUE if negative
; Alters:  Only the Registers returned and the FLAGs (SREG)
Also see:   The PrintAllAINs and PrintScriptProgramHz System Functions.