GOSUB
Der BASIC-Befehl GOSUB springt zur angegebenen Zeilennummer
(nur als Zahlenkonstante erlaubt) und arbeitet den dort angeführten
Programmteil als Unterprogramm ab. Die Programmstelle des GOSUB-Aufrufs
merkt sich der BASIC-Interpreter am BASIC-Stapelspeicher, um später
dort wieder fortsetzen zu können. Das Unterprogramm endet sobald der
BASIC-Befehl RETURN ausgeführt wird und die Programmabarbeitung setzt
beim Programmcode hinter dem aufrufenden GOSUB fort.
Damit wird die Grundidee umgesetzt, Programmteile an unterschiedlichen
Stellen des Programms immer wieder verwenden zu können und zu einer
entsprechende Ersparnis im Umfang und in der Verbesserung der
Übersichtlichkeit, aber auch Wartbarkeit des Programmcodes führt.
Eine Parameterübergabe an das aufgerufene Unterprogramm oder das Zurückliefern von Ergebnissen muss mittels Variablen gelöst werden, über deren Gebrauch sehr sorgfältig Buch geführt werden muss. Es kann sonst zu unerwarteten Nebenwirkungen im Programmablauf kommen, falls Variablen mehrfach verwendet werden.
Es können mit dem BASIC-Befehl GOSUB mehrere Unterprogramme
hintereinander (also ineinander verschachtelt) aufgerufen werden,
allerdings wird immer das zuletzt aufgerufenen Unterprogramm zuerst
beendet. Ein Unterprogramm kann sich auch selbst aufrufen (Rekursion),
wobei die Rekursionstiefe bzw. die Anzahl ineinander verschachtelten
Aufrufe durch den begrenzten BASIC-Stapelspeicher limitiert ist (siehe
Auswertung). Zu viele geöffnete bzw. ineinander verschachtelt
Unterprogramme führen zur BASIC-Fehlermeldung ?OUT OF MEMORY ERROR.
Das theoretische Limit von 26 Verschachtelungen bewegt sich in der
Praxis im Bereich rund um 23, wenn man davon ausgeht, dass im
Unterprogramm noch sinnvolle Aktionen durchgeführt werden sollen (welche
in der Regel ebenso den BASIC-Stapelspeicher gebrauchen).
Existiert die entsprechende Zeilennummer nicht, so erscheint die BASIC-Fehlermeldung ?UNDEF’D STATEMENT ERROR.
Das Verlassen eines Unterprogramms bewirkt zwangsläufig auch, dass
alle dort geöffneten FOR-NEXT-Schleifen beendet werden (und die
Verwaltungsinformationen am BASIC-Stapelspeicher korrekt bereinigt
werden).
Jeder GOSUB-Aufruf benötigt 5 Bytes auf dem BASIC-Stapelspeicher. Diese setzen sich zusammen aus:
- Adresse auf den BASIC-Text unmittelbar nach dem GOSUB (2 Bytes)
- Zeilennummer zur zuvor genannten BASIC-Text-Position gehörend (2 Bytes)
- GOSUB-Token 141/$8D (1 Byte)
Die Werte werden wie am Stapel üblich ausgehend von hohen in Richtung niedriger Adressen abgelegt.
Beispiele
10 PRINT CHR$(147)
20 SP = 20: ZE = 3: A$ = "Guten Tag !": GOSUB 1000: GOSUB 2000
30 SP = 10: ZE = 3: A$ = "Ich bin der Commdore 64": GOSUB 1000: GOSUB 2000
40 SP = 12: ZE = 6: A$ = "Und wie heissen Sie?": GOSUB 1000
100 END
1000 REM Cursorpositionierung
1010 POKE 211,SP :POKE 214, ZE: SYS 58640 : PRINT A$
1020 RETURN
2000 REM Warteschleife
2010 FOR X=0 TO 1500: NEXT X
2020 RETURN
Rekursion
10 REM - DAS RAHMENPROGRAMM
100 INPUT "FAKTORIELLENBERECHNUNG: N=";FA
110 GOSUB 1000
120 PRINT " FAKTORIELLE VON ";FA;"=";FR
130 GOTO 100
1000 REM UNTERPROGRAMM FAKT(FA) -> FR - VERWENDET: I
1010 FR=1: I=1 : REM INITIALISIERUNG
1020 IF I>FA THEN RETURN : REM ABBRUCHBEDINGUNG
1030 FR=FR*I : REM EIN BERECHNUNGSSCHRITT
1040 I=I+1
1050 GOSUB 1020 : REM REKURSION!
1060 RETURN
Im Grunde kompakter und effizienter mit einer FOR-NEXT-Schleife lösbar,
aber hier wird demonstrativ der mathematischen Definition der
entsprechenden Funktion (etwas holprig) genüge getan.
Maximaler Eingabewert ist 22, ohne dass der Fehler ?OUT OF MEMORY erscheint.
Experimentelles
Die maximale Anzahl der Verschachtelungen: (oder “Wieviele GOSUB-Aufrufe verträgt der BASIC-Stapel?”)
10 GOTO 30
20 READ A : REM ANZAHL DER GOSUB AUFRUFE
30 GOSUB 20
40 END
50 DATA 1,2,3,4,5,6,7,8,9,10,11,12,13
60 DATA 14,15,16,17,18,19,20,21,22,23
70 DATA 24,25,26,27,28,29,30,31,32,33
Testlauf:
RUN
?OUT OF MEMORY ERROR IN 30
READY.
PRINT A
26
READY.
Die Konstruktion mit READ-DATA ist eine Methode der Zählung, die den BASIC-Stapelspeicher nicht zusätzlich belastet. Etwaige Schleifenvariablen oder Ausgaben via PRINT würden eine Nutzung des BASIC-Stapelspeichers wegen der Berechnung des jeweiligen Ausdrucks in den Parametern bewirken. Der Überlauf des BASIC-Stapelspeichers träte nämlich dann 2 GOSUB-Aufrufe früher ein.