; GOSUB sub, return address (in w)
; Jumps to the address in the variable sub after storing the return address on a 
; stack in general-purpose RAM. When the destination routine is finished, it 
; jumps to a routine called Return, which fetches the return address off the stack, 
; and jumps to the instruction following the one that invoked Gosub. 

; The Gosub/Return mechanism requires exclusive use of the file-select
; register (fsr). If other parts of the program need to use the fsr, 
; copy it to a variable before altering it and restore it when done. 

        device  pic16c55,xt_osc,wdt_off,protect_off
        reset   start

        org     8
sub     ds      1       ; Destination of Gosub.
temp    ds      1       ; Variables for delays
temp2   ds      1       ; used in demo subroutines. 

; Device data and reset vector
        org     0

start   mov     !rb, #0 ; All outputs for LEDs
        clr     rb      ; Turn LEDs off.
        mov     fsr,#31 ; Point to end of memory
        mov     sub,#One        ; Destination: One. 
        mov     w,pc    ; Save program counter. 
        jmp     Gosub   ; Gosub One. 
        mov     rb,#15  ; LEDs on.      
:loop   djnz    temp,:loop      ; Short delay. 
        djnz    temp2,:loop
        clr     rb      ; LEDs off. 
        jmp     $       ; Endless loop.         

Gosub   mov     indirect,w      ; Return addr on stack.
        dec     fsr     ; Decrement stack pointer. 
        mov     w,sub   ; Destination address to w. 
        jmp     w       ; Go there. 

Return  inc     fsr     ; Increment stack pointer
        mov     w,++indirect    ; w = return addr + 1. 
        jmp     w       ; Jump to return addr. 
; GOSUB (cont)
; Demonstration routines to show successful nesting of 
; three  Gosubs. 
One     mov     rb,#1   ; LED on.       
:loop   djnz    temp,:loop      ; Short delay. 
        djnz    temp2,:loop
        clr     rb      ; LEDs off
        mov     sub,#Two        ; Destination: Two. 
        mov     w,pc    ; Save program counter. 
        jmp     Gosub   ; Gosub Two. 
        jmp     Return  ; Return. 

Two     mov     rb,#3   ; LEDs on.      
:loop   djnz    temp,:loop      ; Short delay. 
        djnz    temp2,:loop
        clr     rb      ; LEDs off
        mov     sub,#Three      ; Destination: Three. 
        mov     w,pc    ; Save program counter. 
        jmp     Gosub   ; Gosub Three
        jmp     Return  ; Return. 

Three   mov     rb,#7   ; LEDs on.      
:loop   djnz    temp,:loop      ; Short delay. 
        djnz    temp2,:loop
        clr     rb      ; LEDs off
        jmp     Return  ; Return.

v�|H��}Ck�#���t9Vjjj