GOSUB / RETURN

Syntax

Syntax: GOSUB label ... label: ... RETURN
Source: pb_cg_emit_gosub_return (pb_codegen.c:1738), pb_cg_emit_gosub_pop_return (pb_codegen.c:1768)

Description

Calls a local subroutine (defined by a label) within the same function and returns to the statement immediately following GOSUB. Unlike CALL (which invokes external DLL functions), GOSUB is an intra-procedure mechanism. The compiler maintains a dedicated GOSUB return address stack in the stack frame (max 32 entries). Each GOSUB pushes the return address; each RETURN pops and jumps to it.

Parameters

ParameterDescription
labelThe name of the subroutine label to jump to. The subroutine must be in the same FUNCTION or SUB and must end with RETURN.
RETURNEnds a GOSUB subroutine and returns execution to the statement after the calling GOSUB.

Example

FUNCTION PBMAIN() AS LONG
    PRINT "Main start"
    
    ' Call local subroutine
    GOSUB PrintBanner
    GOSUB PrintBanner
    
    PRINT "Main end"
    FUNCTION = 0
    
PrintBanner:
    PRINT "===================="
    PRINT "  PowerBASIC x64"
    PRINT "===================="
    PRINT
    RETURN
END FUNCTION

GOSUB - Push Return Address

mov    r10, [rbp - gosub_depth_offset]     ; current depth
cmp    r10, 32                             ; PB_GOSUB_STACK_MAX
jl     __pb_gosub_push_ok_N
mov    rcx, 1
call   [__imp_ExitProcess]                 ; overflow -> abort
__pb_gosub_push_ok_N:
lea    r11, [rbp - gosub_stack_base]       ; stack base
mov    rax, r10
imul   rax, 8                              ; depth * 8
sub    r11, rax                            ; r11 = &stack[depth]
lea    rax, [__pb_gosub_return_N]          ; return address
mov    [r11], rax                          ; store on stack
add    r10, 1
mov    [rbp - gosub_depth_offset], r10     ; depth++
jmp    __pb_label_<routine>_<label>        ; jump to subroutine

RETURN - Pop Return Address

mov    r10, [rbp - gosub_depth_offset]     ; current depth
sub    r10, 1
mov    [rbp - gosub_depth_offset], r10     ; depth--
lea    r11, [rbp - gosub_stack_base]
mov    rax, r10
imul   rax, 8
sub    r11, rax                            ; r11 = &stack[depth-1]
mov    rax, [r11]                          ; load return address
jmp    rax                                 ; indirect jump to return point
__pb_gosub_return_N:                       ; return target

Example Output

GOSUB SayHello
PRINT "Back from GOSUB"
FUNCTION = 0
SayHello:
PRINT "Hello!"
RETURN