; 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. 

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

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.

        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.