Some applications require the use of signed binary numbers to represent values. Typically these values will be stored using a 'two's complement' representation. This article explains how to perform negation on these values.
The example code is for 16-, 24- and 32-bit values stored in FILE0, FILE1, FILE2 and FILE3 where FILE0 is the least significant byte and FILE3 is the most significant.
Negation
To negate a number we change its sign by subtracting it from zero as in 0 - X = -X. On the baseline and mid-range devices the subtract instruction does not propagate a 'borrow' bit making multi-byte arithmetic awkward. The traditional workaround to this is to use a 'one's complement and increment' algorithm instead.
The one's complement operation inverts all the bits in a value turning ones into zeroes and zeros into ones. When applied to a number in twos complement representation this operation is equalivent to calculating -1 - X. Following the complement with an increment converts the results into the required negative, (-1 - X) + 1 = -X.
In the two's complement representation there will always be one more negative value than there are positive ones. For example in 8-bits the range of values is -128 to 127, while for 16-bits it is -32768 to 32767. If we attempt to negate the minimum value the same value will be produced as a result. For example -127 = b'1000000', complemented = b'01111111' and incremented = b'10000000'.
Implementing this in assembler we get the following:
; 16-bit Negation (All devices)
comf FILE0,F ; Complement value
comf FILE1,F
incf FILE0,F ; Then increment
btfsc STATUS,Z
incf FILE1,F
; 24-bit Negation (All devices)
comf FILE0,F ; Complement value
comf FILE1,F
comf FILE2,F
incf FILE0,F ; Then increment
btfsc STATUS,Z
incf FILE1,F
btfsc STATUS,Z
incf FILE2,F
; 32-bit Negation (All devices)
comf FILE0,F ; Complement value
comf FILE1,F
comf FILE2,F
comf FILE3,F
incf FILE0,F ; Then increment
btfsc STATUS,Z
incf FILE1,F
btfsc STATUS,Z
incf FILE2,F
btfsc STATUS,Z
incf FILE3,F
The high performance processors instruction sets more easily support multi-byte arithmetic and using the SUBFWB instruction negation can be performed by subtracting the value from zero.
; 16-bit Negation (High Performance devices)
movlw .0 ; Setup WREG and borrow flag
bcf STATUS,C
subfwb FILE0,F ; Then subtract files from zero
subfwb FILE1,F
; 24-bit Negation (High Performance devices)
movlw .0 ; Setup WREG and borrow flag
bcf STATUS,C
subfwb FILE0,F ; Then subtract files from zero
subfwb FILE1,F
subfwb FILE2,F
; 32-bit Negation (High Performance devices)
movlw .0 ; Setup WREG and borrow flag
bcf STATUS,C
subfwb FILE0,F ; Then subtract files from zero
subfwb FILE1,F
subfwb FILE2,F
subfwb FILE3,F





