JSR – Aufruf eines Unterprogramms

In Assembler wird ein Unterprogramm mit JSR (jump to subroutine) aufgerufen und mit RTS (return from subroutine) beendet.

Das Unterprogramm wird gestartet, indem der Programmschrittzähler auf die Startposition des Unterprogramms gesetzt wird. Damit der Programmablauf nach Beendigung des Unterprogramms im übergeordneten Programm weiter geführt werden kann, muss die Adresse des "Absprungs" festgehalten werden (oder gleich die Adresse des nachfolgenden Befehls).

Für die Speicherung der Rücksprungadresse kein nicht einfach ein Register eingeplant werden; denn im Unterprogramm könnte ein weiteres Unterprogramm aufgerufen werden, was wiederum die Speicherung einer anderen Rücksprungadresse erfordert.

Die Lösung ist die die Ablage der Rücksprungadressen auf einem Stack, der bei JSR beladen und bei RTS abgeräumt wird, wobei die Rücksprungadressen automatisch wieder freigelegt werden.

Hinweis: Der Stack kann zwischendurch vom Unterprogramm mit weiteren Daten gefüllt werden (wenn es einen STO-Befehl gibt). Es muss nur sicher gestellt sein, dass bei Beendigung des Unterprogramm der "alte" Zustand vorliegt.

Zur Demonstration der Verwaltung der Rücksprungadressen wird ein einfacher Modelcomputer entworfen, der nur 5 Befehle kennt.

0 NOP
1 JSR <Adresse>
2 RTS
8 LDA <Wert>
f STP

Als einfallsloses Beispielprogramm wird

0    81    LDA 1
1    18    JSR 8
2    82    LDA 2
3    18    JSR 8
4    83    LDA 3
5    f0    STP
6    80    LDA 0
7    00    NOP
8    87    LDA 7
9    1c    JSR c
a    89    LDA 9
b    20    RTS
c    88    LDA 8
d    20    RTS
e    00    NOP
f    00    NOP

entworfen. Als Ausgabe wird erwartet:
178927893

Die Befehlszeilen 6 und 7 werden nicht erreicht, also nicht ausgeführt. Die Befehle in den Zeilen 5 und 7 könnten ausgetauscht werden. Dann würde das Programm mit der Ausgabe von 0 enden.

Speicherbelegung

Und um den Entwurf weiter zu vereinfachen, werden Operatoren, Operanden und Stack in getrennten RAM-Bausteinen abgelegt. Dann reichen jeweils 6 Speicherplätze aus, und die Adresse kann mit einem Byte benannt werden.
Die Operatoren NOP RTS STP benötigen keinen Operanden. Hier wird zur Vereinfachung ein Operand 0 eingetragen, damit die Zuordnung Operator-Operand in den Speichern zeilenweise erhalten bleibt.

Üblich wäre es, einen Speicher zu benutzen, in dem am Anfang das Programm und am Ende der Stack belegt wird. Wenn nur ein Speicher benutzt wird, muss dieser mehr als 16 Speicherplätze bereit stellen. Dann werden zur Adresssierung (mindestens) zwei Bytes benötigt. Etwa so:

Simulation mit Logisim (download unter Simulation > Logisim)

Um den Microprozessor zu programmmieren, müssen zu Beginn die Speicher belegt werden.

Stack: 0000000000000000
Operatoren: 81818f8081828200
Operanden: 182830007c908000

Dann kann das Programm gestartet werden. Hier im Video wird die Programmausführung Takt um Takt manuell gesteuert.

Anzeige: zunächst alter Wert . nach Reset , im Programm