Let x = x + y (addition)
Let x = x - y (subtraction)

adds or subtracts 16-bit values to produce a 16-bit result, permitting overflow.

PBASIC allows you to add or subtract any two variables--bits, bytes, words, or a mixture--to get a 16-bit result. If a sum is larger than 16 bits, the highest-order bits are lost. If a difference is negative, it is a two's complement number.

The PIC's native instruction set includes 8-bit addition with a carry bit that is set when a sum exceeds 0FFh. This routine for 16-bit addition adds the LSBs first. If a carry occurs, it increments the MSB of the sum, then adds the MSBs.

While it is possible to code a separate subtraction routine in much the same way, it turns out to be easier to convert the number to be subtracted into a negative number instead. This is known as taking the two's complement of a number, and it just a matter of inverting the bits and adding 1. Two's complement numbers occur naturally in the kind of integer math that the PIC performs. Try subtracting 50 from 30 using the native PIC instruction sub. You'll get 236. Of course the answer should be -20. OK, take the two's complement of 20 using the Parallax instruction neg. You'll get 236.

So adding the two's complement of a number is the same as subtracting that number. This technique is used in other instructions throughout this book (e.g., Pause and Sleep) when it is more convenient to increment a negative number up to zero than to decrement a positive number down to zero. The reason is that the instructions inc and dec affect the zero bit, but not the carry bit. When a number is incremented, a carry occurs at the same time the number rolls over to zero. So the zero bit can be used to dete ct a carry when incrementing. This doesn't work when decrementing. The number hits zero one decrement before a carry would occur.
 
 

Demonstrating ADD16 and SUB16.

To see these routines in operation, either run the program with the PSIM simulator, or connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run ADD_SUB.SRC. When you apply power to the PIC, the LEDs will light up in the binary pattern of the answer to the math problem C836h - 2575h, which is A2C1h. That works out to the following binary pattern on the LEDs:

1010 0010 1100 0001

Try adding and subtracting various combinations of n1 and n2 to see different results.


;
; ***************************************************************************
; ***  Bubble Software Parallax to PIC Source Converter. Copyright 1999.  ***
; ***  http://www.bubblesoftonline.com                 email: sales@picnpoke.com  ***
; ***************************************************************************
;
; ADD/SUBTRACT n1, n2
; Add two 16-bit numbers to produce a 16-bit result, permitting overflow. 
; Add the two's complement of one 16-bit number to another 16-bit number
;  to perform subtraction, permitting underflow. 

; Addition: n1 = n1 + n2
; Subtraction: n1 = n1 - n2

; Device data and reset vector
	P = pic16c55
	#include <16c55.inc>   ; processor assembler definitions
	_CONFIG _xt_osc & _wdt_off & _protect_off
        reset   start

        org     8
n1H     Res      d'1'       ; MSB of n1. 
n1L     Res      d'1'       ; LSB of n1. 
n2H     Res      d'1'       ; MSB of n2.
n2L     Res      d'1'       ; LSB of n2.

        org     0

start        MOVLW d'0'                 ; Outputs for LEDs to 
             TRIS 6h
             MOVLW d'0'                 ; display 16-bit result.
             TRIS 7h
             MOVLW 0x00C8               ; Problem: C836h-2575h
             MOVWF n1H
             MOVLW 0x36                 
             MOVWF n1L
             MOVLW 0x25                 
             MOVWF n2H
             MOVLW 0x75                 
             MOVWF n2L
             CALL Sub16                 ; n1 = n1 - n2
             MOVF n1L,w                 ; Show result in binary on 
             MOVWF 6h
             MOVF n1H,w                 ; LEDs connected to ports.
             MOVWF 7h
             GOTO $                     ; Endless loop

Sub16        COMF n2H                   ; Take two's complement
             COMF n2L                   ; of n2. If zero, n2L
             INCF n2L
             BTFSC status,z             ; overflowed, so carry 
             INCF n2H                   ; into n2H.
Add16        MOVF n2L,w                 ; Add the LSBs. If carry,
             ADDWF n1L
             BTFSC status,c             ; increment MSB of sum. 
             INCF n1H                   
             MOVF n2H,w                 ; Add the MSBs  
             ADDWF n1H
             RETLW 0h                   
             
             
             end


; ADD/SUBTRACT n1, n2
; Add two 16-bit numbers to produce a 16-bit result, permitting overflow. 
; Add the two's complement of one 16-bit number to another 16-bit number
;  to perform subtraction, permitting underflow. 

; Addition: n1 = n1 + n2
; Subtraction: n1 = n1 - n2

        org     8
n1H     ds      1       ; MSB of n1. 
n1L     ds      1       ; LSB of n1. 
n2H     ds      1       ; MSB of n2.
n2L     ds      1       ; LSB of n2.

; Device data and reset vector
        device  pic16c55,xt_osc,wdt_off,protect_off
        reset   start
        org     0

start   mov     !rb,#0  ; Outputs for LEDs to 
        mov     !rc,#0  ; display 16-bit result.
        mov     n1H,#0C8h       ; Problem: C836h-2575h
        mov     n1L,#36h
        mov     n2H,#25h
        mov     n2L,#75h
        call    Sub16   ; n1 = n1 - n2
        mov     rb,n1L  ; Show result in binary on 
        mov     rc,n1H  ; LEDs connected to ports.
        jmp     $       ; Endless loop

Sub16   NOT     n2H     ; Take two's complement
        NEG     n2L     ; of n2. If zero, n2L
        snz             ; overflowed, so carry 
        inc     n2H     ; into n2H.
Add16   ADD     n1L,n2L ; Add the LSBs. If carry,
        snc             ; increment MSB of sum. 
        inc     n1H
        ADD     n1H,n2H ; Add the MSBs  
        ret

See also: