Dieses Bild ist ja schon aus der allgemeinen Beschreibung
bekannt.
Rechts ist der Prozessor mit seinen wenigen Registern
dargestellt, links im blauen Rahmen befindet sich der Hauptspeicher mit 256
Speicherplätzen und unten die Bedienung.
Die Bedienung ist nur mit Tasten möglich:
M | man kann in den Speicher wechseln und diesen mit den Daten aus dem SIM-Programm beschreiben. | |
R | R starten das im Speicher vorhandene Programm, das Programm läuft bis zum Ende durch, es lässt sich mit Q vorzeitig beenden. | |
T |
T starten das im Speicher
vorhandene Programm, das Programm läuft bis zum Ende durch, es lässt sich mit Q
vorzeitig beenden.
Das SIM-Programm wird schrittweise in der Größenordnung etwa der
Mikrobefehle abgearbeitet. Die Befehle werden angezeigt. Mit Q ist auch ein vorzeitiges Ende möglich, jedoch erst nach Beendigung des jeweiligen Mikroprogramms. Mikroprogramme können nicht unterbrochen werden (man muss teils sehr oft die Q-Taste betätigen). |
|
L | Mit Load kann man eine SIM-Datei in den Speicher laden, man erspart sich das Eintippen über M. | |
S | Mit Save kann das unter M veränderte oder geschriebene Programm in eine Datei gespeichert werden | |
Q | Q beendet den Simulator und führt zurück in die Bedienoberfläche. |
Unter dem Prozessor werden die „Mikrobefehle“ angezeigt.
Eingabe in den Speicher
Das ist relativ einfach, denn man betätigt die Taste M und kann dann mit den Kursortasten die Speicherplatzposition anwählen und dann dort den Wert eintippen (es kann nur eine Zahl von 0 bis 9 und die Buchstaben a bis f sein):
Im Beispiel wurde die Adresse 20 angewählt, dort kann man
nun ein Zeichen eingaben, es wird sofort an die Stelle gespeichert. War der
Wert falsch, tippt man einfach noch mal die richtige Taste. So kann man auch
korrigieren.
Ist alles richtig kommt man mit Q wieder zurück in den
Simulator, dort könnte man dann mit S den Speicher in eine Datei sichern. Man
sollte die Erweiterung .SIM (Simulation)
verwenden.
Jetzt wollen wir das Programm b11.sim abarbeiten.
Das Programm erzeugt aus der Tastatureingabe im Versuch 2 eine digitale Ausgabe.
Ausgangssituation ist der Simulator in der Bedienoberfläche.
Wir betätigen die Taste L.
Unter dem Speicher erscheint die Aufforderung zur Eingabe des Namens:
Jetzt fehlt uns noch der Versuch! Dazu wird einfach die Taste V getippt, es erscheint unter dem Speicher:
(Das Programm wurde schon mit R gestartet und die 5 eingegeben. Man sieht im Versuch das Ergebnis.)
Im Bild ist weiterhin dargestellt der letzte Mikrobefehl und
die geschalteten Leitungen, der BZ zeigt auf die Adresse 00 (gelbe Leitungen
und neue Eingabe), die Datenleitung schafft eine Verbindung zum Akku (rote
Leitung) – der eingegebene Wert landet im Akku.
Das BZH hat die Adresse des Speicherplatzes A2, der nach der
Eingabe verwendet wird.
Im Anschluss erfolgt die Beschreibung des Programms.
Größeres Assembler-Programm – Beispiel
Als Ausgabe gibt es Quasi-LED-Balken:
Das zu schreibende Programm soll aus der Eingabe eines Zeichens (über Tastatur) die entsprechenden Balken ansteuern.
Das Beispiel zeigt die Darstellung für eine 5.
Im Prinzip soll eine Wandlung der
Zeichen von hexadezimal auf dual vorgenommen werden!
Eigentlich ist das ganz einfach, denn nach der Eingabe der
Zahl 5 ist die Bitfolge 0101 bereits im Akku vorhanden. Das Problem besteht
darin, die einzelnen Bits auf 4 Speicherplätze zu verteilen!
Wie macht man so was?
Einen Befehl gibt es nicht dafür und man sollte nicht glauben,
dass das ein Problem unseres kleinen Rechners ist, das gibt es real auch nicht,
zumindest der 8086 kann das auch nicht.
Wir haben also ein Standard-Problem zu klären!
Lösung:
Man muss Bitweise herausbekommen ob das Bit 1 oder 0 ist. Das realisiert man mit „sogenannten Masken“, man vergleicht eine unbekannte Bitfolge mit einer bekannten, der Maske.
Und schon wieder gibt es ein Problem: es gibt keinen
Vergleichs-Befehl derart, dass man herausbekommt ob das Bit 1 oder 0 ist. Es
gibt generell keinen Vergleichsbefehl oder gar eine if-Anweisung
wie in Pascal oder C!?
Auf der Assembler-Ebene muss man versuchen für sein Problem
ein Flag zu nutzen. Das geht für unseren Fall übers N-Flag:
Das ganze noch einmal exakt:
0111
+ 0001
---------
1000 => 2-er Komplement
0000 Wert nach Maskierung
+ 1000 Subtraktion
durch Addition des 2-er Komplements
---------
1000 Das
1. Bit ist 1, d.h. negativ, das N-Flag wird gesetzt (N=1)
Mit dieser Arbeitsweise ist auch zugleich darauf hingewiesen, dass die Subtraktion und dann auch alle weiteren arithmetischen Operationen immer auf die Addition zurückgeführt werden kann, man braucht nur ein leistungsstarkes Addierwerk!
Dementsprechend kann nun eine 0 oder 1 auf den Speicherplatz
02 gespeichert werden
(N=1 eine 0 speichern, N=0 eine 1).
Mit den 3 weiteren Bits verfahren wir in gleicher Weise,
es werden die Masken 0100, 0010 und 0001 gebraucht.
Man legt alle Masken auf Speicherplätze oder man vereinbart
nur eine Maske und schiebt die 1 immer einen Platz weiter. In dem Beispiel wird
die erste Variante genutzt, die zweite geht aber auch, es gibt einen
Verschiebe-Befehl.
Damit ist das Prinzip der Bearbeitung schon klar – muss nur noch umgesetzt werden! Genau das bereitet dem Anfänger große Schwierigkeiten – es soll erklärt werden.
Auch wenn der Assembler vieles schon macht, die Speicherplatzverwaltung obliegt dem Programmierer!
Organisation
Wir gehen mal so ran, als hätten wir genügend Speicherplatz,
das Programm soll wieder beim Speicherplatz 20
beginnen. Belegt sind 00 (Eingabe), 01 (Ausgabe), 02 … 08
Sonderausgaben/Versuche) und FA ... FF (Systemspeicherplätze).
Die Masken könnte
man in der ersten Zeile ganz rechts 0C …
0F. Außerdem brauchen wir eine 0,
soll auf 0B liegen und einen Speicherplatz zum Zwischenspeichern eines
Wertes, soll auf 11 liegen. Damit können wir schon mal anfangen:
Wir brauchen die Masken 0001 = 1(16), 0010 = 2(16), 0100 =
4(16) und 1000 = 8(16).
Hier wird schon ein wenig vereinfacht, da wir ohnehin die Maske
0001 brauchen können wir diese auch gleich als 1 benutzen (16 = hexadezimal):
org | 0B | |
kon | 0 | ;auf Speicherplatz 0B wird eine 0 (0000) gespeichert |
kon | 1 | ;auf Speicherplatz 0C eine 1 (0001) (kon erhöht die Adr. um 1) |
kon | 2 | ;auf Speicherplatz 0D eine 2 (0010) |
kon | 4 | ;auf Speicherplatz 0E eine 4 (0100) |
kon | 8 | ;auf Speicherplatz 0F eine 8 (1000) |
Nun folgt das Programm ab Adresse 20:
Unterprogramm
Unterprogramme müssen einen Namen bzw. Adresse haben, das erledigen wir mit Marken:
Ob nun das 1.Bit 1 oder 0 ist weiß man nicht, hängt von der Eingabe ab, also testen:
m8e: | lda | B | ;SPl. 0B nach Akku (auf 0B steht eine 0) |
spa | 2 | ;Akku nach SPl. 02 (Anz.1.Stelle) |
Ab Marke m4 wird nun das 2.Bit untersucht.
Das Wichtigste ist, dass zunächst einmal, dass der
eingegebene Wert wieder bereit gestellt wird. Den haben wir ja vorsorglich auf
den Speicherplatz „ret“ abgelegt, also laden wir ihn
von da in den Akku:
Diese Arbeitsweise garantiert, dass ein UP von beliebiger Stelle aus aufgerufen werden kann, es wird immer nach Beendigung des UP der nächste Befehl nach Aufruf des UP abgearbeitet. Im realen Rechner gibt es für die Speicherung der Rücksprungadressen zumeist einen Stak-Speicher, der dann auch den Aufruf eines UP aus einem UP zulässt, das geht in unserem kleinen Rechner nicht so einfach (in der LST-Datei unten ist das UP und auch das HP geschlossen dargestellt).
Hauptprogramm
Das Hauptprogramm ist auch nur eine Folge von den schon bekannten Befehlen, also keine besondere Kennung. Das Einzige ist, dass man eine Adresse festlegen muss, ab der es beginnen soll – und dass ist erst mal schwierig. Da wir mit dem UP angefangen haben, müssen wir zählen wie viele Plätze es im Speicher braucht. Man sollte es aber nicht unmittelbar hinters UP legen, manchmal ändert sich da noch etwas.
Wir legen fest, es soll bei A0 beginnen:
;----- HP ---------- | |||
org | a0 | ;(1) HP ab SPl.A0 | |
start: | lda | 0 | ;(2) HP Start Spl.00 in Akku |
sup | m8 | ;(3) UP.Aufruf | |
sp | start | ;(4) erneuter Start HP | |
org | ff | ;(5) Startadresse | |
kon | a |
Startadresse 20 wäre falsch, wir würden mit dem UP beginnen,
das wird komplett falsch. Man kann das
ja einfach probieren, indem im Simulator die Startadresse auf 20 gesetzt wird.
Ändert man nach der Abarbeitung mit der falschen
Startadresse diese wieder auf A0, kann es sein, dass das Programm nun auch
nicht mehr richtig läuft!
Und das ist das Problem oder die Fähigkeit eines
Assemblerprogramms, es werden in den Bereich des Programms Werte gespeichert,
denn es gibt keine Trennung zwischen Programm und Daten. Das passiert so auch
in der realen Rechnerwelt, z.B. kann man auch in der Programmiersprache C ein
Array von 10 Speicherplätzen vereinbaren und aus Versehen speichert man einen
Wert auf Speicherplatz 20 des Array. Es gibt keine Fehlermeldung aber das
Programm geht nicht mehr wie es soll – ist doch ganz klar, der Wert
überschreibt einen Teil des Programms und damit gibt es Probleme.
Mit Assemblerprogrammen kommt man in alle „Ecken“ des Speichers und Prozessors des Rechners – also ist bei der Nutzung eines realen Rechners Vorsicht geboten!
Man muss das aber nicht nur negativ sehen, denn das gibt uns auch die Möglichkeit neuer Programmiermethoden – das Programm kann sich selbst verändern, also selbstprogrammierende Programme kann man erstellen, das ist noch ein weites Forschungsfeld.
Nun noch einmal das ganze Programm, aber zunächst der
logische Ablauf als
Programm-Ablauf-Plan (PAP):
Folgende Bezeichnungen gelten:
Es wurde jede Zeile kommentiert, das muss man nicht, hilft hier aber zum Verständnis.
zurück zur Start-Seite / weiter Bedienoberfläche |