Jetzt, da unser VNR Laden und Speichern kann, soll er auch Verarbeiten - lassen wir ihn also rechnen!
Zu diesem Zweck hat das Applet wieder eine Erweiterung erfahren: Das Feld "Opcodes anzeigen" im Steuerfenster. Weil es immer schwieriger wird, sich die Maschinensprachecodes der verschiedenen Befehle zu merken, zeigt der VNR nach Anklicken des Kästchens statt einer Zahl einen sogenannten Opcode (operation code, Befehlskode) aus max. fünf Buchstaben. Inklusive dieses Applets kennen wir dann folgende Befehle (RAM[x] bezeichnet den Wert im RAM an Adresse x):
Fünf-Zeichen-Opcode | VNR-Befehl |
LA 38 | LDA absol. 38 (oft geschrieben LDA #38)
Akku := 38; |
LM 38 | LDA mem 38 (oft geschrieben LDA 38)
Akku := RAM[38]; |
LI 38 | LDA mem indir. 38 (oft geschrieben LDA (38))
Akku := RAM[ RAM[38] ]; |
SA 30 | STA absol. 30 (oft geschrieben STA #30)
RAM[30] := Akku; |
SM 30 | STA mem 30 (oft geschrieben STA 30)
RAM[ RAM[30] ] := Akku; |
+ 31 - 31 * 31 / 31 |
ADD, SUB, MUL, DIV mem 31 (oft
geschrieben ADD 31 etc.)
Akku := Akku + RAM[31]; etc. Nicht: Akku := Akku + 31; ! |
Um die Schlichtheit des VNR zu betonen, beherrscht unser Exemplar kein
ADD absol. etc. Man überlegt sich leicht, daß für
solche Befehle keine neuen Komponenten wie z.B. Register notwendig wären;
jeder neue Befehl vergrößert aber das Steuerwerk des Rechners.
Auch deswegen gibt es kein ADD absol., sehr wohl aber, wie wir
bald sehen werden, die sehr häufig gebrauchten Befehle INC
und DEC (increase und decrease, diese bewirken ein
"AKKU := AKKU + 1" bzw. "... - 1").
Im Applet kommt auch ein Divisionsbefehl vor. Dieser liefert
natürlich kein ganz präzises Ergebnis (mit Nachkommastellen),
weil unser Beispiel-VNR nur ganze Zahlen kennt.
Wer trotzdem nicht glaubt, daß der VNR richtig rechnet, der kann
dem Rechner ab jetzt auch eigene Werte vorgeben: Einfach eine beliebige
Speicherzelle des RAMs anklicken und einen neuen Wert eingeben (am Besten
die Simulation vorher neu starten).
Was das Rechenprogramm genau tut, ist unterhalb des Applets zu lesen:
Hier sollte die Ausgabe des Java-Applets "Von-Neumann-Rechner - Rechnen mit dem VNR" erscheinen. Wenn Sie statt dessen diesen Text sehen, unterstützt ihr Browser kein Java!
Was das Programm in diesem Applet tut:
Zunächst werden eine Addition und eine Multiplikation durchgeführt. Sehr schön ist hier die Abfolge Laden-Rechnen-Speichern zu sehen; der an jeder Rechnung zwangsläufig beteiligte Akkumulator muß vorher mit einem Wert initialisiert und nachher "gesichert" werden.
Anschließend wird berechnet. Man beachte, daß jetzt nicht mehr auf jeden Rechenbefehl gleich ein STA folgt, weil nämlich idealerweise ein Rechenbefehl das Ergebnis des vorherigen gleich weiterverwendet. Ziel eines Maschinensprache-Programmierers wird es sein, den Anteil von Lade- und Speicherbefehlen im Verhältnis zu den Rechenbefehlen, die ja in diesem Falle die eigentliche Arbeit tun, zu reduzieren. Damit spart man doppelt: Das Programm wird kürzer und schneller, denn gerade die Zugriffe auf das "langsame" RAM kosten Zeit.
Ein unbedarfter Programmierer hätte den zu berechnenden Term so wie er oben steht in VNR-Code umgesetzt, also folgendermaßen:
Benötigte Daten:
Adresse | Wert |
10 | 30 |
11 | 40 |
12 | 5 |
13 | 6 |
14 | 7 |
Befehle:
LDA 10 ADD 11 STA #20 LDA 12 ADD 13 STA #21 LDA 20 DIV 21 MUL 14 |
30 + 40 "Zähler" speichern 5 + 6 "Nenner" speichern "Zähler" durch "Nenner" Ergebnis mal 7 |
Die beiden fett markierten Befehle lassen sich einsparen, wenn man, wie im Applet, erst den "Nenner" und dann den "Zähler" berechnet:
LDA 12 ADD 13 STA #21 LDA 10 ADD 11 DIV 21 MUL 14 |
5 + 6 "Nenner" speichern 30 + 40 "Zähler" durch Nenner Ergebnis mal 7 |
Man beachte, daß es nichts "bringt", wenn man das "* 7" als zum "Zähler" gehörig ansieht und vorher einschiebt. Sehr wohl aber hilft diese Anordnung, den Rundungsverlust der Ganzzahl-Division zu reduzieren: Es gilt nämlich bei ausschließlicher Verwendung ganzer Zahlen:
((30+40)/(5+6)) * 7 = 42 , hingegen
((30+40)*7) / (5+6) = 44 ,
was näher am Dezimalbruch-Ergebnis 44,54... liegt.
Durch diese Ausführungen zur Maschinenprogrammierung sollte klar geworden sein, warum auch heute noch, im Zeitalter komfortabler Hochsprachen wie Java, zeitkritische Teile von Programmen in Maschinensprache kodiert werden - je nach verwendeter Sprache und Optimierungsgrad spricht man von einem Unterschied zwischen handoptimiertem und hochsprachlichem Kode von Faktor 2 bis 10 (oder noch wesentlich höher bei interpretierten Sprachen).
Carsten Kelling 1996 (); letzte Änderung: 21. Februar 1997 |