Unsere bisherigen Programme liefen allesamt linear ab: nach einem Befehl kam stets der Befehl von der nächsthöheren Adresse und der Ablauf des Programmes war stets gleich. Ein nicht-lineares Programm könnte bei dem obigen Rechenbeispiel z.B. auf das Ergebnis der Division reagieren. In den meisten Fällen könnte es brav dividieren, im Falle einer Division durch 0 aber zu einem Unterprogramm verzweigen, welches eine Fehlermeldung ausgibt und den VNR anhält. Verzweigen oder auch Springen bedeutet, daß der nächste Befehl eben nicht vom Nachfolger der aktuellen Adresse geholt wird; das automatische Inkrementieren (Erhöhen um 1) des Programmzählers in der Decode-Phase reicht dann nicht mehr aus, es muß eine Möglichkeit hinzukommen, den Programmzähler mit beliebigen Werten zu laden. Tatsächlich sind die Sprungbefehle nicht viel mehr als Ladebefehle für den Programmzähler (statt für den Akkumulator).
Die einfachere Art eines Sprungbefehls ist der unbedingte Sprung. Hierbei wird in den Programmzähler in der Ausführungsphase des Befehls ohne Wenn und Aber ein neuer Wert geladen - der in der Decode-Phase automatisch erzeugte Wert des Programmzählers wird einfach überschrieben. Dieser Befehl existiert bei uns als JMP (JuMP) absol. und JMP mem, mit gleicher Bedeutung von "absol." und "mem" wie bei LDA.
Die bedingten Sprungbefehle werden, wie der Name schon sagt, nur ausgeführt, wenn eine bestimmte Bedingung erfüllt ist. Ansonsten wird der nächste Befehl so von der nächsthöheren Adresse geholt, als sei ein NOP ausgeführt worden. Wie sieht nun die Sprung-Bedingung aus? Es gibt hier mindestens zwei unterschiedliche Ansätze:
Für die Neugierigen jetzt nur ein letzter Hinweis: Auch der
Wert des Programmzählers läßt sich jetzt per Maus einstellen
(z.B. auf 10 hexadezimal...). Wer lieber erst nachlesen möchte, was
das Programm im Applet tut, blättert weiter nach unten.
Hier sollte die Ausgabe des Java-Applets "Von-Neumann-Rechner - Die Sprungbefehle" erscheinen. Wenn Sie statt dessen diesen Text sehen, unterstützt ihr Browser kein Java!
Das Programm sind eigentlich zwei: Das erste (Adressen 0 bis 8) läuft
unendlich lange, denn an Adresse 8 steht ein unbedingter Sprungbefehl
zu Adresse 0. Wer genug gesehen hat, sollte zu Beginn einer Fetch-Phase
10 hexadezimal (Beginn des zweiten Programms) in den Programmzähler
eintragen. Beide Programme bewirken fast das Gleiche: der Wert von Adresse
30 wird nach 38 kopiert, der von 31 nach 39, von 32 nach 3a usf. Dazu benutzen
die Programme zwei Zeiger: Der Wert an Adresse 20 besagt, von
wo das nächste Datenwort geholt werden soll (deswegen steht hier
am Anfang 30), der an Adresse 21, wohin das Datenwort geschrieben
werden soll (Adresse 38 und folgende).
Man beachte, daß die ersten beiden Befehle der Routinen für
das Kopieren ausreichen, weitere sechs werden benötigt, um die beiden
Zeiger um 1 zu erhöhen.
Doch jetzt kommt der Unterschied: Das erste Programm kopiert nach dem
Erreichen von Adresse 37 ungeniert weiter, also den Wert von 38 nach 40,
von 39 nach 41, usw., beliebig lange, bis der ganze Speicher ab Adresse
30 mit den gleichen acht Binärwörtern gefüllt sein wird.
Das zweite Programm ab Adresse 10 hexadezimal ist explizit so konstruiert,
daß es nur genau eine Kopie der acht Datenwörter anfertigt.
Dazu benutzt es statt JMP absol. den bedingten Sprung JLE absol. (Jump
absolutely if Less or Equal). An Adresse 24 erwartet dieses Programm
einen dritten Wert (neben den beiden Zeigern), der ihm sagt, wann es mit
dem Kopieren aufhören soll. Ein Subtraktions-Befehl an Adresse
18 wird benutzt, um diese End-Adresse mit dem Ziel-Zeiger zu vergleichen
(wir könnten auch mit dem Quell-Zeiger vergleichen, aber der Ziel-Zeiger
steht an dieser Stelle des Programmes gerade im Akkumulator); direkt auf
dieses SUB folgt das JLE und kann die flags aus der ALU abfragen.
Dann wird durch acht IN-Befehle das Eintreffen neuer Daten simuliert, die
dann wieder kopiert werden können.
Carsten Kelling 1996 (); letzte Änderung: 21. Februar 1997 |