------------------------------------------------------ Gosub/Return jumps to a subroutine address after storing the current address on a stack in memory. When Return is invoked, the program resumes at the line following the latest Gosub. The PIC instruction set includes call and ret, which work much like PBASIC's Gosub and Return. The trouble is that the stack that call uses to store return addresses is only two levels deep in the PIC 16C5x series. This limits you to two nested calls. In other words, a called routine can call only one other. If that routine makes a call, the program will never find its way back the starting point. By contrast, PBASIC permits 16 nested Gosubs. The demonstration program shows how you can break the two-level limit by having your program establish and manage a stack of return addresses for separate Gosub and Return routines. The calling program must put the address of the destination subroutine into sub, and the current contents of the program counter into w. It then jumps to Gosub, which stores the return-address information on a stack at the end of memory. When the subroutine is through, it jumps to Return. Return retrieves the return address from the stack, adjusts it to point to the line after the previous jmp Gosub, and goes there. You can nest one subroutine for each byte of memory available. For example, if your program uses memory locations 8 through 19, then locations 20 through 31 are available for use as 12-level Return stack. There is a restriction in using Gosub. Since a program can read and store only the lower eight bits of the program counter, all of the subroutines must be in the lowest 256 instruction words of a program-memory page. Demonstrating Gosub. To see Gosub 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 GOSUB.SRC. When you apply power to the PIC, the LEDs will light up one at a time, demonstrating that the program executed all three nested subs and returned to the main program. ------------------------------------------------------ ; 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.          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         device  pic16c55,xt_osc,wdt_off,protect_off         reset   start         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.