If...Then

compares two 16-bit numbers by subtraction and reports one of the three possible cases: n1 < n2; n1 > n2; and n1 = n2.

PBASIC's If...Then statement allows you to compare two numbers up to 16 bits in length and make a decision (jump to a program address) based on the outcome of the comparison. Parallax assembly language offers the same capability through its compare-and-jump instructions (cja, cjae, cjb, cjbe...), but these are limited to 8-bit values.

The subroutine Comp16 compares 16-bit numbers and reports the results through the w register as follows:
 
 

        0       n1 = n2
        1       n1 > n2
        2       n1 < n2

Since it performs its comparisons through w, it does not alter n1 or n2.

To use Comp16 as a replacement for PBASIC's If...Then, use either a compare-and-jump instruction or Branch to process the result returned in w. See Branch for a method of handling compound logic expressions.

Demonstrating Comp16.

To see Comp16 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 COMP16.SRC. When you apply power to the PIC, the LEDs will light up in the binary pattern returned by the comparison (in this case 01, where 1 represents a lit LED). Try various combinations of n1 and n2 to see the three codes.


; COMPARE n1, n2
; Compares two 16-bit numbers by subtracting one from the other and reports the 
; outcome by a code in the w register. Does not alter n1 or n2. Uses the status
; register bit PA2 to preserve the z flag from subtraction of the LSBs. If you 
; adapt this code for use in PICs other than 16C5x series, make sure that this
; bit is available. If it isn't, use a bit in one of the file registers instead. 

Z_      =       PA2     ; Unused status bit as extra Z flag. 
        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. 
        mov     n1H,#0C8h       ; Compare 0C836h to
        mov     n1L,#36h        ; 2575h. 
        mov     n2H,#25h
        mov     n2L,#75h
        call    Comp16  ; Call the subroutine. 
        mov     rb,w    ; Show result on LEDs
        jmp     $       ; Endless loop

; Upon return, a code in w will indicate the outcome of the comparison. 
; If n1 > n2 then w = 1. If n1 < n2 then w =2. If n1 = n2 then w = 0. 
Comp16  clrb    Z_      ; Clear aux Z bit.
        mov     w,n2L   ; w = n2L
        subwf   n1L,0   ; w = n1L-n2L
        snz             ; Copy z bit to Z_. 
        setb    Z_
        mov     w,n2H   ; If n1L-n2L underflowed, 
        jc      :cont   ; then increment n2H (same
        mov     w,++n2H ; as decrementing n1H).
        snz             ; If n2H overflows, n1 must be < n2
        retw    2       ; so return with 2 in w.
:cont   subwf   n1H,0   ; w = n1H-n2H 
        sc              ; If n1H underflows, n1<n2 retw 2 ; so return with 2 in w. jnb Z_,:cont2 ; By now we're sure n1'>=n2. 
        snz             ; If both z and Z_ are set, 
        retw    0       ; both subtractions resulted in 0, so
:cont2  retw    1       ; n1=n2. Otherwise n1>n2.