Computer-Basiswissen 2
von Otmar Feger
Programmablaufsteuerung
Wird
ein Befehl aus dem Befehlsspeicher abgeholt, muss die
Programmablaufsteuerung diesen entschlüsseln. Das geschieht durch
einen Festwertspeicher der einzelnen Signale nebeneinander und oder
nacheinander erzeugt um die Befehlsausführung durchzuführen.
Dieser Festwertspeicher nennt man das Mikroprogramm.
Wie Befehle im
Einzelnen im Computer ablaufen zeigt Bild 12 in einer vereinfachten
Darstellung. Zuerst erklären wir die Komponenten der Schaltung.
Auf
der linken Bildseite sehen Sie den Taktgenerator, der den
Befehlszähler steuert. Die Länge eines Befehlszählers
entspricht dem Adressraum des Programm- und Datenspeichers Bei 16
Zählstufen lassen sich bis 65.535 Befehle ansteuern. Dieser
Speigrößen können nur teilweise integriert sein, sie
sind jedoch extern anschließbar. Heute üblich Taktraten liegen zwischen 12 und 50 MHz.
Beim
Programmstart steht der Befehlszählerinhalt auf Null, und der
Inhalt des ersten Befehls wartet darauf an den Mikroprogrammspeicher
übergeben zu werden. Die ersten Stufen des Befehlszählers
steuern den Mikroprogrammspeicher an. Dieser erzeug dann in zeitlicher
Reihenfolge die Signale die zur Ausführung des aktuellen Befehls
erforderlich sind. An schließend greift der Befehlszähler
auf den nächsten Befehl zu und der Zyklus wiederholt sich. Die
Befehlszyklenzeit ist also niederer als die Taktrate. Beträgt die
Taktrate z. B. 12 MHz (8051) so ist die Befehlszyklenzeit 1 MHz. Das
sind immerhin eine Million Befehle je Sekunde.
Die parallelen
Verbindungen zwischen den Controller-Einheiten nennt man einen Bus, In
Bild 12 sind sie graphisch zusammen gefasst, auch wegen der
einfacheren bildlichen Darstellung.. Es gibt Adress-, Daten- und
Steuerbusse. An einem Befehl sei der weitere Ablauf erläutert.
MOV AUSGABE_1,ADRESSE_1000
; Transportbefehl: Bringe
Inhalt der der
Adresse 1000 aus dem Datenspeicher zur <Ausgabeeinheit 1>
MOV ist die englische Bezeichnung für
Bewegung, AUSGABE_1 ist der Ausgabe-Port 1 und nach dem Strichpunkt dem
folgt ein Kommentar. Die Reihenfolge der Ausdrücke von links nach
rechts stammt wohl von den Mathematikern, die ihre Gleichungen so
schreiben und bei den Computerentwicklungen mitarbeiteten. Bei der
Programmierung wird viel mit Symbolen gearbeitet, Befehle, Daten und
Adressen sind als Symbole zu vereinbaren. Das lässt Programme
leichter schreiben und lesen.
Software
Wie schon
erwähnt arbeitet man mit Assemblern. Jedem Befehl bekam eine
Buchstabenkombination die ihm eine eindeutige Bedeutung zugeordnete.
(MUL, DIV, MOV usw.). Wichtig war, dass man Symbole für Marken
Adressen und Konstanten einführte. Marken bestimmten Sprungziele
von Unterprogrammen, Interrupts oder Zeilen in der Programmliste um die
Bedeutung von Programmteilen zu kennzeichnen. Zu jedem Befehl kann auch
ein Kommentar hinzugefügt werden.
Es gibt auf der untersten
Programmebenen mehrere Befehlskategorien: Transportbefehle (MOV), Set-
und Löschbefehle, Arithmetik- und Logikbefehle (ADD, SUBB, MUL,
DIV – OR, AND), Sprungbefehle zur Programmsteuerung (SET, CLR),
Vergleichsbefehle (> < =), Bitverarbeitungsbefehle und Befehle
aus zusammengesetzten Fumktionen.
Bild 16 zeigt den Ausschnitt
eines solchen Programms. Über die Details braucht man sich
zunächst keine Gedanken machen. Auf der linken Seite sind einige
Marken als Sprungziele oder zur Kennzeichnung. Die Befehle (zuerst der
Operationscode und dann der Adressteil) befinden sich in der
nächsten Spalte. Am rechten Rand sind, durch
„Strichpunkt“ getrennte Kommentare möglich.
Der
Assembler ordnet allen Symbolen Befehlen, Daten oder Konstanten zu,
prüft auf logische und Syntaxfehler und gibt bei Fehlerfreiheit
ein ablauffähiges Programm aus. Besondere Befehle, die
mehrere Funktionen ausführen werden hier kurz beschrieben.
Indexbefehle
Indexregistern
sind Register die eine indirekte Programmierung erlauben. Das bedeutet
der Inhalt des Indexregisters zeigt auf eine Adresse auf die man
über das Indexregister zugreifen kann. Eine häufige Anwendung
ist das Durchlaufen einer Liste. Der Inhalt des Indexregisters steht
auf dem Listenanfang. Über das Index-Register kann nun mit einem
Befehl auf die Liste zugegriffen werden, z. B. Lade den Inhalt aus der
Adresse auf die das Index hinweist in den Akkumulator. Erhöht man
der Inhalt des Indexregisters jeweils um 1, kann man auf diese Art
innerhalb einer Programmschleife die Liste durchlaufen.
Vermindere eine Zahl um 1 und Springe wenn das Inhalt gleich 0
Dieser Befehle ist besonders bei Zählschleifen nützlich, um solange zu Verzweigen bis der Wert 0 erreicht ist.
Vergleiche
den Inhalt des Akkumulators mit einer Zahl oder dem Inhalt eines direkt
oder indirekt adressierten Speicherplatzes.
Besonders nützlich bei der Lösung von Suchaufgaben.
Unterprogrammsprünge und Interruptspünge
Auf
Sprünge in ein Unterprogramm und auf Sprünge die ein
Interrupt auslöst sei hier näher eingegangen.
Benötigt
man bestimmte Programmteile mehrfach, sind diese nicht mehrfach
zuschreiben. Solle eine Division mit beispielsweise 32 bit große
Zahlen von einem Mikrocontroller mit 8 bit Verarbeitungsbreite
durchgeführt werden ist dazu ein eigenes Programm erforderlich.
Legt man diesen in ein Unterprogramm so kann es von beliebig vielen
Stellen beliebig oft vom Hauptprogramm aus aufgerufen werden. Ein
solches Unterprogramm kann sehr umfangreich sein. Das Unterprogramm
endet mit dem Rücksprung an die Adresse, die nachdem
Unterprogrammaufruf folgt. Unterprogrammen
erlauben erst die Bildung höherer Programmiersprachen da sie
beliebige Inhalte, also auch Sprachkonstrukte, enthalten können.
Durch die Möglichkeit der Verschachtelung sind beliebig viele
Ebenen denkbar.
Ein Interrupt ist ein Sprungbefehl der ein internes
oder externes Ereignis auslöst. Interne Ereignisse mögen
Überläufe integrierter Zähler/Zeitgeber, Abschluss
einer internen A/D-Wandlung sein. Ursachen für externe Interrupts
können z. B. Signalwechsel an einem Eingangspin sein.
Beispielsweise löst ein Regensensor nach einem Millimeter
Niederschlag einen Interrupt aus der dann im Interrupt-Programm einen
Zäher inkrementieret (+1), eventuell auf das Erreichen eines
Schwellwerts abfragt und dann an die vorher unterbrochenen Stelle
zurückkehrt. Ein anderes Beispiel ist die Meldung einer Seriellen
Schnittstelle um ein ankommendes Signal anzukündigen.
Da die
meisten Mikrocontroller mehrere verschiedene Interrupte zulassen, kann
man den einzelnen Interrupt-Quellen unterschiedliche Prioritäten
zuweisen. Das Hauptprogramm verbietet oder erlaubt bei Bedarf einzelne
oder alle Interrupts. Bild 14 veranschaulicht die Verhältnisse
bei Unterprogrammen und Interrupts.. Die Sprünge sind blau, die
Rücksprünge gelb markiert.
Weitere Programmsteuerbefehle
Bei
Unter- und Interruptprogrammen kann man davon ausgehen, dass das
unterbrochene Programm verschiedene Register in Daten geladen hat, die
nicht verloren gehen dürfen. Deshalb gibt es spezielle Befehle
die die fraglichen Registerinhalte am Anfang in einen besonderen Teil
des Datenspeicher (dem Stack) ablegen und am Ende der Unter- und
Interrupt-Programme wieder aus dem Stack zurückholen.
Außer
dem Assemblerprogramm gibt es weitere Programme, um die
Programmierarbeit zu unterstützen. Der Linker fasst mehrere
Assemblerprogramme zusammen. Sei es, um vorhandene Programmteile
einzubinden oder dass mehrere Programmierer gleichzeitig an einer
gemeinsamen Aufgabe arbeiten Der Simulator erlaubt
Programmabläufe schritt- oder teilweise zu durchlaufen und damit
alle Details nachzuvollziehen. Zur Fehlersuche nahezu unverzichtbar.
Es gibt auch Ladeprogramme, die ein Programm unmittelbar in einen
Controller oder ein EPROM speichern. Ein EPROM ist ein extern
anschließbarer Speicher dessen Inhalt durch UV-Licht
löschbar ist. Es gibt auch Controller mit integriertem EPROM,
Diese sind jedoch teuer. In einer größeren Serienproduktion
(etwa ab einigen 1000 Stück) werden Programme unmittelbar auf den
Chip mitintegriert.
Die Mikrocontroller verschiedener Firmen haben
Architekturen mit eigenen Befehlssätzen und Benennungen. Es ist
also jeweils ein eigener Assembler erforderlich. Um von Rechnertypen
unabhängig zu sein entwickelte man zuerst bei den
Großrechnern rechnerunabhängige Programmsprachen deren
Übersetzung die auf allen Rechnertypen lauffähig waren. Die
Programme, die diese Sprachen in die jeweiligen Computer
übersetzten nennt man Compiler. So gab es beispielsweise COBOL
für kaufmännische und FORTRAN für mathematische
Anwendungen Es folgten eine ganze Reihe weitere, verbesserte Sprachen.
In gleicher Weise entwickelte man für Mikrocontroller das Programm
BASIC. BASIC-Compiler mussten ebenfalls an das jeweilige
Assemblerprogramm angepasst werden. Nachfolger von BASIC war dann die
Sprache C. Unterschiedlichen Mikrocontroller-Typen benötigen
jeweils eigene Compilerprogramme.
Höhere Programmiersprachen
bringen für den Programmierer viele Vereinfachungen. So musste er
sich z. B. nicht mehr um Wortlängen kümmern und es entfallen
viele Transportbefehle da Kommandos in höheren Sprachen sich
meistens aus vielen Assemblerbefehlen zusammensetzten. Höhere Programmiersprachen sind jedoch hier nicht das Thema.
Es folgen einige typische Programmierbeispiele um die Vorgehensweise darzulegen.
Beispiel 1; Aus drei Zahlen die größte ermitteln und abspeichern
Wie
schon erwähnt arbeiten Programme die Befehle nacheinander ab. Es
sollen die größte aus drei Zahlen A_ZAHL, B_ZAHL und C_ZAHL,
ermittelt und das Ergebnis in D_ZAHL gespeichert werden. In Programmen
kann und soll man komplizierte Sachverhalte durch Flussdiagramme
darstellen. Sie dienen der Dokumentation der Vergehensweise damit man
den Sachverhalt später nicht durch die einzelnen Befehle
nachvollziehen muss. Nach längerer Zeit weiß sowieso nicht
mehr, was man sich damals gedacht hat. Das Beispiel ist für
die Praxis unbedeutet. Da sich aber jeder etwas darunter vorstellen
kann eignet es sich besonders zur Darstellung der Programmiermethode.
Bild 15 zeigt das Flußdiagramm und Bild 16 das Programm dazu.
Der
Akkumulator (AKKU) ist das rechenfähige Register, das auch
Größer-/Kleiner-Vergleiche mittels des Subtraktions-Befehls
SUBB ermöglicht.
Inhalt von Adressen werden in eckige
Klammern geschrieben, z. B. <Alpha>, Die Adresse selbst, z. B.
von (Alpha) wird mit offenen Klammern eingerahmt, >Alpha<.
Beispiel 2: Löschen eines Speicherbereichs
Viel
häufiger hat man mit Listen zu tun. Beispielsweise um etwas zu
suchen oder zu sortieren. Das hier beschriebene Beispiel lässt
sich mit wenigen Befehlen dazu anpassen (Bilder 17 und 18).
Beispiel 3: Uhrzeiten programmieren
Vorgehendweise
und Voraussetzungen fassen die Bilder 19 bis 21 zusammen. Die Bilder
22 bis 24 zeigen dazu das Flussdiagramm. Ein integrierter Zähler
ist so konfiguriert, dass er alle Millisekunde überläuft und
einen Interrupt auslöst. Danach wiederholt sich der Zyklus. Das
Interrupt-Progamm wird also jede Millisekunde aufgerufen und ermittelt
die verschiedenen Uhrzeiten.
Zusammenfassung
Durch die
Unterprogrammtechnik sind beliebige Programme in ein Unterprogramm
einzubinden. Der Name des Unterprogramms kann gleichsam als eigener
Befehl aufgefasst werden. Auf diese Weise lassen sich ganz neue
Befehlssätze entwickeln die auf verschieden Anwendungsaufgaben
anzupassen sind. So wird beispielsweise ein Malprogramm andere Befehle
als ein Fahrplan oder Textprogramm benötigen. Üblicherweise
gibt es dann mehrere Ebenen (Abstraktionen) übereinander
angeordnet Programme um komplexe Aufgaben lösen zu können.
PC Programmieren
Bei
Programmen die auf PC laufen sollen hat der Programmierer eine andere
Situation vor sich als in der Mikrocontroller-Welt. Nach dem
Einschalten eines PC startet automatisch das Programm BIOS (Basis
Imput Output System). Dieses stellt die grundsätzlich Verbindung
mit Tastatur, der Maus, den Speicherlaufwerken (Festplatten und Disks),
Bildschirm und den externen Schnittstellen her. Das ist die erste und
unterste Programmebene. Das dann geladene Betriebssystem stellt die
zweite Ebene dar. Das Betriebssystem, meistens Windows, lädt aus
einer eine Vielzahl externer Peripheriegeräten wie Tastaturen,
Drucker, Bildschirme und Graphikkarten, sowie viele andere extern
Geräte, Treiber, die die Lieferanten dieser Geräte zur
Verfügung stellen.
Zudem stell das Betriebssystem
leistungsstarke Werkzeuge zur Verfügung, um die Arbeit des
Programmierers zu erleichtern. Genannt sei die Fenstertechnik,
Schriften, Farbenverwaltung und Interanbindung aber auch interne
Archivverwaltungen usw.. Auf das Betriebssystem setzt dann das
Anwenderprogramm als dritte Ebene auf. Innerhalb diesem gibt es
naturgemäß wieder weitere Ebenen (Bild 25).
Stellen wir
uns das vereinfachte Vorgehen eines Programmierers beim Entwickeln
eines Graphik-Programms vor. Zuerst listete er die Werkzeuge (Tools)
die dem Zeichner zu Verfügung stehen müssen auf. Er stellt
sie auf dem Bildschirm als Symbole (Icons) dar die man mit der Maus
oder der Tastatur aktivieren kann. Beispielsweise Strecken, Kreise,
Vierecke, Strichstärken, Farbauswahl, Kopier und
Löschfunktionen usw. Das ist seine untere Programmebene. Jedes
Icon führt zu einem Unterpogramm das den entsprechenden Befehl
ausführt und das Ergebnis auf dem Bildschirm darstellt. Diese
Unterprogramme sind teilweise sehr komplex und benötigen wiederum
eigene Ebenen. Nach dem Prinzip Eingabe, Verarbeiten und Ausgabe arbeiten die meisten Programme.
Ausblick
Auf
der Hardware-Seite steht die Leistungssteigerung im Vordergrund. Dabei
spielen Multi-Rechnerkerne eine zunehmende Rolle. So wie man bei den PC
zur Leistungserhöhung, beispielsweise bei Google, Systeme mit
vielen 1000 PC vernetzte um leistungsfähige Suchalgorithmen zu
realisieren. Diese überwachen sich gegenseitig und schalten
fehlerhafte Teile ab ohne den Betrieb zu stören (Fehlertolerant).
Mikrocontroller mit bis zu 8 Rechnerkernen für spezielle
Anwendungen wurden ebenfalls entwickelt.
Multirechnerkerne
analysieren und verarbeiten den aktuellen Befehlsdurchsatz oder die
Befehlsfolgen, um sie so weit wie möglich in Teile zu zerlegen,
parallel abzuarbeiten und damit den Befehlsdurchsatz zu beschleunigen.
Die PC-Taktgeschwindigkeiten reichten inzwischen bis in den
Gigaherzbereich, (1.000.000.000 = 1 Giga). Speicher ereichten
Kapazitäten mehrer Terrabytes Das sind noch mal drei Nullen mehr.
Auf
der untersten Ebene das Assemblerprogramm, dann das Betriebssystem und
dann das compilierte Anwenderprogramm, Je nach Anwendungsbereich folgen
die Ebenen eines Textverarbeitungs- oder Graphikprogramm, einem
Datenbanksystem zur Lagerverwaltung, ein Bank- oder ein
Klinikverwaltungssystem usw. Man spricht da von Schichtenmodellen oder Abstraktionsebenen. Der
Computer ist ein Werkzeug mit unbegrenzten Möglichkeiten. Es wird
einmal möglich sein, dass er für Problemebereiche
selbstständig Lösungen sucht und dann dazu die passenden
Programme selbst schreibt.
zurück: Teil 1