| 3. Aufbau Praktikumsrechner & Betriebssoftware | Lösungsvorschläge zu den Praktischen Übungen |

3.2/1

## 3.2 Das Monitorprogramm

### 3.2.1 Allgemeines

Ein Rechensystem, dessen Arbeitsspeicher ausschließlich aus einem flüchtigen Schreib-/Lese-Speicher besteht, dessen Inhalt demnach beim Abschalten der Versorgungsspannung verloren geht, ist nur bedingt funktionsfähig: Da der Inhalt des Arbeitsspeichers beim Wiedereinschalten nicht definiert ist, ist der Prozessor nicht in der Lage, sinnvolle Operationen auszuführen. Es sind nicht einmal Grundfunktionen wie das Lesen der Tastatur möglich.

In der Frühzeit der Computer hat man sich damit beholfen, den Prozessor zunächst einmal - durch Sperren des Taktsignals - anzuhalten, um dann ein Programm unter Umgehung des Prozessors direkt in den Speicher zu schreiben.

Auch der in den Anfangsjahren unseres Praktikums eingesetzte Praktikumsrechner wurde nach diesem Prinzip betrieben: Zuerst wurde ein kurzes Hilfsprogramm eingegeben, indem man mittels Tastatur zunächst die Adresse auswählte und dann den zugehörigen Befehl in binärer Form in den Speicher schrieb. Dieses Programm führte dann automatisch die Inkrementierung der Adresse durch, und man konnte sich für die Eingabe des eigentlichen Programms auf die Eingabe des Befehls - natürlich immer noch in binärer Form - beschränken.

Stürzte das zu testende Programm dann ab, was, wie Sie mittlerweile wahrscheinlich wissen, nicht die Ausnahme, sondern die Regel ist, so war im allgemeinen auch das mühsam eingetippte Hilfsprogramm zerstört, und man mußte wieder völlig von vorn anfangen !

Wie Sie aus dieser kurzen Darstellung schon ersehen können, ist diese Methode der Programmierung nicht nur sehr fehleranfällig, sondern auch äußerst mühselig und zeitaufwendig. Daher ist die Forderung nach einem Programmsystem verständlich, das bestimmte Grundfunktionen des Rechners schon unmittelbar nach der Inbetriebnahme bereitstellt.

Bei diesem System muß es sich nicht unbedingt um ein Monitorprogramm oder ein komplettes Betriebssystem handeln. Insbesondere bei größeren Rechnersystemen, die auf jeden Fall mit externen Speichermedien wie Platten- oder Diskettenlaufwerken oder Bandmaschinen verbunden sind, existiert oft nur ein sogenannter Urlader (Bootstrap Loader), der den Rechner in den Stand setzt, ein Betriebssystem "von außen" in den Arbeitsspeicher zu laden und zu starten.

Bei einem kleineren System, wie dem von Ihnen benutzten Praktikumsrechner, der auch ohne angeschlossene Peripheriegeräte betriebsfähig sein soll, ist es dagegen günstiger, zumindest ein einfaches Betriebssystem in einem Festwertspeicher mitzuliefern, das dem Benutzer sofort nach dem Einschalten zur Verfügung steht und bei der Erstellung von Programmen, bei der Fehlerbeseitigung und der Benutzung der verschiedenen Komponenten des Rechners Hilfestellung gibt.

3.2/2

Anforderungen an ein Monitorprogramm

Wie oben bereits erwähnt, muß ein Rechner nach dem Einschalten in einen definierten Grundzustand überführt werden. Dazu gehören insbesondere das Setzen des Stackpointers und die Initialisierung der verschiedenen Rechnerkomponenten, insbesondere der Schnittstellen. Diese Aufgaben müssen von einem "eingebauten" Monitorprogramm übernommen werden.

Die Hauptaufgabe eines Monitors besteht aber in der Unterstützung des Programmierers bei der Eingabe und beim Austesten von Programmen. Der angebotene Komfort ist dabei vorwiegend von dem für den Monitor zur Verfügung stehenden Speicherplatz abhängig.

Da die Entwicklungssysteme auf der Basis von Einplatinencomputern noch vor einigen Jahren aufgrund der hohen Preise für Halbleiterspeicher mit sehr kleinen Monitorprogrammen auskommen mußten, war die Zahl der verfügbaren Funktionen auf ein absolut notwendiges Minimum beschränkt, das die Programmierung des Prozessors in Maschinensprache mit Hilfe einer Hexadezimaltastatur erlaubte.

Mit dem Preisverfall der Halbleiterbauelemente wurden jedoch immer umfangreichere und damit komfortablere Programme möglich, so daß ein Monitor mittlerweile durchaus über einen einfachen Assembler/Disassembler und eine ganze Reihe weiterer komplexer Funktionen verfügen kann.

Der im Praktikumsrechner benutzte Monitor ist in einem EPROM vom Typ 2764 untergebracht. Dieser Baustein wurde schon im Abschnitt 3.1 kurz vorgestellt. Er besitzt eine Organisation von 8k·8 bit, also eine Kapazität von 8 kbyte. Davon sind zur Zeit knapp 4 kbyte vom Monitor belegt, die restlichen 4 kbyte sind für die schon in KE1 angesprochenen Hilfsroutinen reserviert.1)

Für ein reines Entwicklungssystem, auf dem hauptsächlich Programme für andere Rechner getestet und zum Laufen gebracht werden sollen, sind diese Routinen relativ uninteressant. Sollen die fertigen Programme aber auf demselben System ausgeführt werden, auf dem sie entwickelt wurden, ergibt sich durch eine solche Bibliothek eine bedeutende Einsparung an Speicherplatz, vor allem aber eine große Zeitersparnis bei der Programmierung. Bei geschickter Anwendung der Bibliotheksprogramme kann ein Anwenderprogramm dann zu einem großen Teil aus Unterprogrammsprüngen zu den Hilfsroutinen bestehen.

Selbsttestaufgabe S3.2-1:
Überlegen Sie sich, warum die Routinen der Bibliothek nicht in einem Programm benutzt werden können, das auf einem anderen Rechner ausgeführt werden soll.

3.2/3

### 3.2.2 Aufbau und Flußdiagramm des Monitors

Der Aufbau und die Funktionsweise eines Monitors sollen hier beispielhaft anhand des im Praktikumsrechner benutzten Monitors erklärt werden. Allerdings werden wir bei einigen Funktionen, die unserer Meinung nach schlecht gelöst wurden, auf andere bzw. bessere Methoden zurückgreifen.

Zum besseren Verständnis sehen Sie in Bild 3.2-1 die Adreßraumbelegung des Rechners.

Bild 3.2-1: | Die Adreßraumbelegung des Praktikumsrechners |

3.2/4

Der gesamte adressierbare Bereich beträgt 64 kbyte. Davon werden 8 kbyte ($0000 - $1FFF) vom RAM belegt, weitere 8 kbyte vom EPROM ($E000 - $FFFF). Außerdem sind noch zwei Steckplätze für Speicherbausteine vorhanden, die aber in der Ihnen zugeschickten Grundausstattung des Praktikumsrechners nicht benutzt werden.

Das RAM enthält neben den Anwenderprogrammen die Systemvariablen, die in den ersten vier 256-byte-Seiten untergebracht sind, und den (System-)Stack. Da seine Größe statisch nicht feststeht, wird der Stackpointer zunächst auf das Ende des RAM-Bereichs gesetzt. Der Stack wächst dann rückwärts auf die Anwenderprogramme zu. Er benötigt in der Regel weniger als 200 byte 2), kann aber erheblich größer werden, falls ein Programm sehr stark verschachtelt ist oder die Parameter für Unterprogramme auf dem Stack übergeben werden.

Insbesondere Programmierfehler (z.B. das Vergessen, auf dem Stapel abgelegte Werte wieder herunterzunehmen) können dazu führen, daß der Stack in den Programmbereich "hineinwächst" und damit das Anwenderprogramm zerstört.

Das Flußdiagramm in Bild 3.2-2 zeigt in stark vereinfachter Form den allgemeinen Ablauf des Monitorprogramms.

Bild 3.2-2: | Das Flußdiagramm des Monitors |

3.2/5

Nach dem Rücksetzen, ausgelöst durch die Taste C bzw. automatisch beim Einschalten des Rechners (Power on Reset), springt der Rechner in die Initialisierungsroutine. Diese Routine kann sehr vielfältige Aufgaben haben. Dazu gehören z.B. Selbsttests, Feststellung des RAM-Bereichs und der angeschlossenen Geräte oder Initialisierung der Schnittstellen.

Zwei Funktionen müssen aber auf jeden Fall ausgeführt werden: Der Stackpointer S muß gesetzt werden und die vom Monitor benötigten Variablen müssen ihre Startwerte erhalten. Dazu wird ein Bereich des ROM in den Systembereich des RAM kopiert, wo die Werte dann vom Monitor benutzt und bei Bedarf verändert werden können.

Selbsttestaufgabe S3.2-2:
Der 6809-Prozessor sperrt alle Unterbrechungen, bis ein Wert in den Stackpointer S geschrieben wurde. Warum ?

Zum Abschluß der Initialisierung wird eine Meldung ausgegeben, die anzeigt, daß der Rechner jetzt betriebsbereit ist, und eventuell noch einige Informationen über den Zustand des Systems gibt. Die Meldung Ihres Rechners wurde schon in KE1, Abschnitt 1.2.1, erklärt.

Der Kommandointerpreter ist das Kernstück des Monitors. Hier werden die Kommandos von der Tastatur eingelesen, ausgewertet und die entsprechenden Monitorroutinen aktiviert.

Das Assemblerlisting der Interpreterschleife in Bild 3.2-3 entspricht nicht der augenblicklichen Implementierung im Praktikumsrechner. Nach ihrem Muster soll die Interpreterschleife aber in einer der nächsten Versionen in den Monitor eingebaut werden. Durch die spezielle Codierung der Tasten (siehe Tabelle 1.2-2 in KE1) wird sowohl die Auswertungsroutine als auch die Sprungtabelle sehr kurz.

Die Interpreterschleife springt nach der Ausführung einer Funktion nicht automatisch wieder in die Tastaturabfrage (HALTKEY), und zwar deshalb, weil in den Monitorroutinen in der Regel nach weiteren Eingaben gefragt wird. Beim Erkennen einer für die laufende Routine ungültigen Eingabe wird die Routine beendet. Nur wenn der Kommandointerpreter im Akku B keinen gültigen Befehl findet (TESTB), wird die Tastatur erneut abgefragt.

Der Pseudobefehl FDB im Listing bedeutet "Form Double Byte". Es handelt sich also nicht um einen ausführbaren Befehl, sondern um die Anweisung an den Assembler, an dieser Stelle einen 16-bit-Wert einzutragen, in diesem Fall die Startadressen der Monitorroutinen.

Falls die Sprungtabelle sich im RAM-Bereich des Rechners befindet, ist der Austausch der Routinen durch den Benutzer möglich. Für die Tasten F1 - F3 gilt dies auch im vorliegenden Monitor (siehe auch KE1). Ein konkretes Beispiel dazu finden Sie in Unterabschnitt 3.2.5.

3.2/6

    ; Interpreterschleife
    ;
    FALSCH:    JSR  CLRDISP   ; Anzeige löschen
               LDA  #$D3      ; 7-Segmentcode für '?'
               LDX  #0        ;  in der letzten Stelle
               JSR  SHOWA     ; anzeigen
               JSR  HALTKEY   ; auf einen Befehl warten
    SCHLEIFE:  TSTB           ; Code in Akku B testen
               BPL  FALSCH    ; keine Funktionstaste, zurück
               ANDB #$7F      ; Bit 7 löschen
               LSLB           ; 2 Bytes pro Eintrag
               LDX  #SPRUNGTB ; Basisadresse der Tabelle
               JSR  [B,X]     ; indirekter Sprung zur Routine
               BRA  SCHLEIFE  ; Endlos-Schleife
    ;
    ; In jeder Funktionsroutine: Fehlerbehandlung bei unzulässiger Funktionstaste
    ;
    FEHLER:    CLRB           ; Tastencode löschen
               RTS            ; zur Interpreterschleife
    ;
    ; Sprungtabelle
    ;
    SPRUNGTB:  FDB  #FEHLER   ; + den Tasten '+' und '-' sind
               FDB  #FEHLER   ; - keine Routinen zugeordnet
               FDB  #ADDRESS  ; A   |
               FDB  #DATA     ; D   |
               FDB  #REGIST   ; R   | ansonsten werden die
               FDB  #GO       ; G   |
               FDB  #SAVE     ; S   | jeweiligen Startadressen
               FDB  #LOAD     ; L   |
               FDB  #TRACE    ; T   | der Routinen in die
               FDB  #INSERT   ; F1  |
               FDB  #DELETE   ; F2  | Tabelle eingetragen
               FDB  #DUMP     ; F3  |

Bild 3.2-3: Listing des Kommandointerpreters

Praktische Übung P3.2-1:
Schreiben Sie eine Interpreterschleife, die Kommandos aus vier beliebigen Hexadezimalziffern (zwei Bytes) verwendet. Benutzen Sie zur Eingabe des Befehls die Routine SHOWADR.

3.2/7

### 3.2.3 Aufbau der Hilfsroutinen

Beim Betrieb eines Rechners werden einige Standardfunktionen immer wieder benötigt. Um sie nicht jedesmal neu programmieren zu müssen und damit Arbeitszeit und Speicherplatz zu verschwenden, wird von vornherein eine Reihe dieser Funktionen als komplette Unterprogramme in den Monitor eingebaut.

Einen Teil der Hilfsroutinen haben Sie bereits in KE1, Abschnitt 1.2.2, kennengelernt. Dazu gehören die Ein-/Ausgaberoutinen und die Umwandlungsroutinen, z.B. vom Hexadezimal- in den Siebensegment-Code.

Daneben werden von einigen Monitorroutinen noch Unterprogramme zum Editieren der Parameter und zur Adreß- bzw. Dateneingabe gebraucht.

Als einfaches Beispiel ist in Bild 3.2-4 die Routine CLRDISP abgebildet, die die eingebaute 7-Segment-Anzeige löscht:

    ;CLeaRDISPlay:   Siebensegmentanzeige löschen
    ;
    CLRDISP:  PSHS X,CC        ; CPU Register retten
              LDX   #DISPL     ; Display, rechte Stelle (S0)
    CL1:      CLR   ,X+        ; löschen
              CMPX  #DISPL+16  ; bis DISPL+7 (S7)
              BNE  CL1         ;
              PULS  X,CC       ; Register restaurieren
              RTS              ; Ende CLRDISP
    ;
    DISPL     EQU   $F020      ; Startadresse der Anzeige, s. Abschnitt 3.1

Bild 3.2-4: Listing der Routine CLRDISP

Alle von der Routine benutzten Register werden zu Beginn auf den Stapel gerettet und vor der Beendigung wieder heruntergenommen, so daß der alte Zustand der CPU wiederhergestellt wird. Die Funktion der Routine ist einfach: Ein Register zeigt auf die erste Stelle der Anzeige. Dann wird in einer Schleife eine 0 in die entsprechende Adresse geschrieben und das Register inkrementiert, bis alle acht Stellen gelöscht sind. Durch den Pseudo-Opcode EQU wird der Variablen DISPL die Startadresse der Anzeige zugewiesen 1).

Obwohl die Hilfsroutinen nur Standardfunktionen realisieren, müssen sie nicht unbedingt trivial sein. Das läßt sich recht eindrucksvoll an der Routine SHOWADR nachweisen. Sie liest eine Adresse (zwei Bytes) zyklisch von der Tastatur in das Y-Register und stellt diese im Adreßfeld der Anzeige dar, bis eine Funktionstaste gedrückt wird. Deren Tastencode steht dann im Akku B zur Verfügung.

3.2/8

SHOWADR bedient sich mehrfach der Hilfsroutinen HALTKEY und SHOWD7SG, die ihrerseits weitere Routinen aufrufen. Bild 3.2-5 dient zur Veranschaulichung des Ablaufs: Bei der Ausführung von SHOWADR werden insgesamt acht weitere Routinen aufgerufen, die maximale Schachtelungstiefe ist 5.

Bild 3.2-5: | Beispiel zur Unterprogramm-Schachtelung |

Aus dieser Sicht wird auch die Bedeutung der Zusicherung aus KE1, Abschnitt 1.2.2, klar, daß nur die Inhalte der explizit angegebenen Register verändert werden und alle anderen Daten unverändert bleiben. Anderenfalls wären die Auswirkungen eines solchen Funktionsaufrufs für den Programmierer kaum noch nachvollziehbar. Die einzige Möglichkeit, sich vor unliebsamen Überraschungen zu schützen, bestünde vor jedem Aufruf einer Hilfsroutine in der Rettung aller weiterhin benötigter Register auf den Stack und deren Restaurierung nach der Rückkehr.

Praktische Übung P3.2-2:
Lesen Sie die Routine SHOWADR aus dem EPROM und tragen Sie in das Diagramm von Bild 3.2-5 die absoluten Adressen ein, an denen die Hilfsroutinen aufgerufen werden. Achtung: Die Hilfsroutinen werden zum Teil mit relativen Sprüngen (LBSR) aufgerufen. Analysieren Sie die Routine INDATA. Disassemblieren Sie das Programm, kommentieren Sie die Befehle und zeichnen Sie das Flußdiagramm.

3.2/9

### 3.2.4 Aufbau der integrierten Monitorroutinen

Abgesehen von der Hexadezimaltastatur gibt es auf dem Tastenfeld des Rechners vier Tasten, denen keine Routine zugeordnet ist: Die Funktionstaste C führt einen Systemstart durch und die Taste F4 gibt eine Interruptanforderung an den Prozessor. (Auf die Interruptbehandlung werden wir im Unterabschnitt 3.2.5 noch näher eingehen). Die Tasten '+' und '-' haben verschiedene Bedeutungen, auf die wir bei der Behandlung der einzelnen Monitorroutinen zurückkommen. Die übrigen Tasten rufen die verschiedenen Funktionen des Monitors auf, die bereits in KE1, Abschnitt 1.2.1, erklärt wurden und die sich grob in vier Klassen einteilen lassen:

1. Bearbeitung des Speichers:
   - Tasten A, D: Adressen und Daten editieren
   - Tasten F1, F2: Einfügen und Entfernen von Daten und Befehlen
   - Taste F3: Durchsehen eines Speicherbereichs
2. Bearbeitung der Prozessor-Register: Taste R
3. Laden und Sichern von Anwenderprogrammen: Tasten L, S
4. Ausführung der Anwenderprogramme:
   - Taste G: Starten eines Programms
   - Taste T: Einzelschrittausführung
   - Befehl SWI1*) : Unterbrechung bzw. kontrollierte Beendigung
   - Taste F4: Programmabbruch von außen

A. Speicherbearbeitung

Die Speicherbearbeitung wirft keine größeren Probleme auf. Es stehen geeignete Hilfsroutinen zur Verfügung, die den Großteil der auszuführenden Teilaufgaben übernehmen, so daß nur noch das Gerüst zusammengesetzt werden muß.

Die Tasten '+' und '-' haben bei diesen Routinen die Aufgabe, eingegebene Daten zu übernehmen und den Adressenzeiger zu inkrementieren bzw. dekrementieren.

Anhand der Routine ADDRESS demonstrieren wir Ihnen hier einmal die Implementierung einer Routine von der Problemstellung bis zum fertigen Programm mittels der Ihnen bekannten Hilfsroutinen.

Zunächst die Anforderungen:

1. Löschen der Anzeige und Ausgabe der Kennung "Ad" im Operationsfeld,

2. Ausgabe der zu editierenden Adresse und des zugehörigen Datums,

3. Eingabe einer neuen Adresse bzw. inkrementieren/dekrementieren der Adresse mit den Tasten '+' und '-',

4. Rückkehr aus der Routine, wenn eine andere Taste gedrückt wurde als eine Ziffer oder die Tasten '+' bzw. '-'.

3.2/10

Aus den Anforderungen wird das Flußdiagramm nach Bild 3.2-6 entwickelt:

Bild 3.2-6: | Flußdiagramm der Routine ADDRESS |

Bild 3.2-7 zeigt die Routine in Assemblerschreibweise. Dabei ist bei der Benutzung der Routine SHOWADR zu beachten, daß das Y-Register im ersten Befehl gelöscht wird. Wenn Sie also nicht unbedingt eine neue Adresse eingeben möchten, springen Sie zum zweiten Befehl der Routine, was in diesem Fall ohne weiteres möglich ist, da SHOWADR keine Register auf den Stapel rettet. Da das Löschen des Y-Registers (LDY #0) vier Bytes beansprucht, muß eine neue Einsprungadresse berechnet werden.

Anmerkung: Sie können diese Routine anstelle der "Standard"-Routine benutzen, allerdings mit einigen Einschränkungen.

3.2/11

    ; Routine    ADDRESS:    Adresse editieren
    ;
    ; Ausgabe der Kennung und Holen der Adresse
    ;
    ADDRESS:PSHS A,X,Y,CC	; Register retten
    	JSR  CLRDISP	; Anzeige löschen
    	LDD  #$775E	; 7-Segmentcodes für "Ad"
    	LDX  #6		; im Operationsfeld
    	JSR  SHOWD	; anzeigen
    	LDY  <ADR	; zu editierende Adresse holen
    			; zum Zeichen "<" siehe das
    			; Programmierhandbuch
    ; Adresse editieren
    ;
    W:	LDB  ,Y		; zugehöriges Datum in Akku B
    	LDX  #0		; im Datenfeld
    	JSR  SHOWB7SG	; anzeigen
    	LDX  #2		; Anzeige im Adreßfeld
    	LDU  SHOWADR+1	; Startadresse aus Sprungtabelle
    	JSR  4,U	; Aufruf ohne Löschen von Y
    ;
    ; Ergebnis von SHOWADR interpretieren
    ;
    	CMPB #$81	; letzte Taste
    	BHI  R		; >$81?, dann fertig
    	BEQ  $2		; =$81(Taste '-')?, dann dekrementieren
    	LEAY 2,Y	; Zeiger inkrementieren (um 2, da
    			; wieder dekrementiert wird)
    	LEAY -1,Y	; Zeiger dekrementieren
    	BRA  W		; und erneut editieren
    ;
    ; falls Ergebnis nicht "+" oder "-", geordnetes Beenden des Programms
    ;
    R:	STY  <ADR	; neue Adresse ablegen
    	PULS A,X,Y,CC	; Register restaurieren
    	RTS		; zurück zum Monitor
    ADR	EQU  $....	; 2 Speicherplätze für Adresse

Bild 3.2-7: Listing der Routine ADDRESS

3.2/12

Praktische Übung P3.2-3:
Ermitteln Sie die effektive Sprungadresse im Befehl "JSR 4,U" im obigen Programmlisting für den im µR implementierten Monitor. Wie kommt diese Adressierung zustande? Kann der 6809-Assembler den Befehl verarbeiten ? Welche Einschränkungen bzw. Änderungen müssen Sie vornehmen, um diese Routine statt der "Standard"-Routine benutzen zu können? Assemblieren Sie die Routine ADDRESS und testen Sie sie aus. Entwerfen Sie nach dem Muster der eben vorgestellten Adreßeingaberoutine eine Dateneingaberoutine.

Bei den Routinen INSERT und DELETE zum Einfügen und Entfernen von einzelnen Speicherstellen ergibt sich eine Schwierigkeit:

Die nachfolgenden Daten müssen im Speicher verschoben werden. Die Operation des Verschiebens selbst ist einfach, man muß sich aber darüber im Klaren sein, daß nicht der gesamte Speicherinhalt verschoben werden darf, da sonst auch der Stapelspeicher verschoben würde und der Rechner zwangsläufig abstürzt. Außerdem befinden sich oft mehrere Programme oder Programmteile gleichzeitig im Speicher, von denen nur eines geändert werden soll.

Die Frage ist also, welcher Speicherbereich verschoben wird. Wir haben uns dafür entschieden, jeweils 256 Bytes oberhalb der zu editierenden Adresse zu verschieben. In der Regel werden die von Ihnen geschriebenen Programme kürzer sein, und es besteht die Möglichkeit, zu anderen Programmen einen ausreichenden Zwischenraum zu lassen, so daß diese von der Verschiebung nicht betroffen sind.

Eine weitere Lösung des Problems besteht in der Festlegung eines Arbeitsbereichs, außerhalb dessen die Monitorroutinen nicht arbeiten. In diesen "geschützten" Bereich kann dann der Stack angelegt werden.

Praktische Übung P3.2-4:
Schreiben Sie eine Routine für die INSERT-Funktion und testen Sie sie aus.

B. Bearbeitung der Prozessor-Register

Mit der Taste R wird die Routine zur Darstellung und zum Editieren der Register des Mikroprozessors aktiviert. Dabei handelt es sich selbstverständlich nicht um die realen Register des Prozessors (,die zum Betrieb des Monitors benötigt werden und auch auf keinen Fall von außen verändert werden können), sondern um einen reservierten Teil des Systembereichs ($0000-$03FF), der die Werte enthält, die beim Start eines Anwenderprogramms in den Prozessor geladen werden und bei Unterbrechung des Programms die "geretteten" Registerinhalte wieder aufnimmt.

3.2/13

Die Routine besteht, wie aus dem Flußdiagramm im Bild 3.2-8 ersichtlich, aus zwei Hauptteilen: Auswahl eines Registers und Editieren des Inhalts. Sie funktioniert ganz ähnlich wie die DATA-Routine, beide unterscheiden sich hauptsächlich in der Funktion der Tasten '+' und '-'. Während in der DATA-Routine lediglich die Adresse inkrementiert bzw. dekrementiert wird, verwaltet die Hilfsroutine zur Parameterauswahl einen Zeiger auf eine Tabelle, der der eigentlichen Editierroutine den Zugriff auf die benötigten Parameter erlaubt. Das sind in diesem Fall die Kennung des Registers (wird im Adreßfeld angezeigt), die "Länge" des Registers (1 oder 2 Bytes), die für die Auswahl zwischen SHOWADR und SHOWDATA gebraucht wird, und ein Verweis auf die Zero-Page-Adresse, in der sich der Registerinhalt befindet.

Bild 3.2-8: | Flußdiagramm zur Routine REGIST |

Da diese Routine ebenfalls nicht in der beschriebenen Form implementiert ist, haben wir das Listing einer universell nutzbaren Routine im Bild 3.2-9 angegeben, mit der es beispielsweise auch möglich wäre, die Registerinhalte der Peripheriebausteine zu editieren, und zwar allein durch die Ausgabe der entsprechenden Kennung im Operationsfeld und die Angabe der Basisadresse der benötigten Parametertabelle.

    ; Routine REGIST: Register editieren
    ; Kennung ausgeben und Startwerte setzen
    REGIST:	PSHS A,X,Y,CC	; Register retten
    	JSR  CLRDISP	; Anzeige löschen
    	LDD  #$5079	; 7-Segmentcodes für "rE"
    	LDX  #6		;   im Operationsfeld
    	JSR  SHOWD	;   ausgeben

3.2/14

    	LDY  #REGPAR	; Basisadresse der Tabelle
    	CLRA		;   mit erstem Register beginnen
    	JSR  EDIT	; zur Editierroutine
    	PULS A,X,Y,CC	; Register restaurieren
    	RTS		; zurück in den Monitor
    ; Editieren
    EDIT:	PSHS A,X,Y	; Register-Nummer und Basisadresse retten
    	LDB  #5		; 5 Bytes
    	MUL		;   pro Eintrag
    	LEAY B,Y	;   zur Basisadresse addieren
    	LDD  ,Y++	; 7-Segmentcode für Kennung
    	LDX  #0		;   im Datenfeld
    	JSR  SHOWD	;   anzeigen
    	LDX  #2		; Editieren im Adreßfeld
    	TST  ,Y+	; 1- oder 2-byte-Daten
    	PSHS Y		; Zeiger auf Parameter retten
    	BEQ  BYTE	; 0 für 1 Byte
    	LDY  [,Y]	; Datenwort editieren
    	LDX  SHOWADR+1	; dazu Sprung nach SHOWADR ohne
    	JSR  4,X	;   Löschen von Y, s. Bild 3.2-7
    	TFR  Y,X	; Datenwort nach X
    	PULS Y		; Zeiger wiederherstellen
    	STX  [,Y]	;   und Datum ablegen
    EDIT2:	PULS A,X,Y	; Register restaurieren
    	CMPB #$81	; Taste '-' gedrückt ?
    	BLS  $1		; >$81?  (Tastencode für '-')
    	RTS		;   dann zurück ins Hauptprogramm
    	BSR  PARAM	; sonst Parameter ändern
    	BRA  EDIT	; und wieder editieren
    BYTE:	LDY  #0		; nicht benutzte Anzeigestellen
    	JSR  SHOWYD	;   löschen
    	PULS Y		; Zeiger auf Datum restaurieren
    	LDA  [,Y]	; Datenbyte editieren
    	LDX  SHOWDATA+1	; dazu Sprung nach SHOWDATA ohne
    	JSR  2,X	; Löschen von A
    	STA  [,Y]	; und wieder ablegen
    	BRA  EDIT2	; zurück nach EDIT
    ; Parameter ändern
    PARAM:	PSHS CC		; Status retten
    	BEQ  MINUS	; falls letzte Taste = $81
    	INCA		; nächster Parameter
    	CMPA -1,Y	; mit Tabellenende vergleichen
    	BLE  $1		; noch nicht überschritten
    	CLRA		; sonst zum Tabellenanfang
    	BRA  R		; fertig
    MINUS:	DECA		; vorheriger Parameter
    	BPL  $2		; ·0 ? dann o.k.
    	LDA  -1,Y	; sonst letzter Parameter
    R:	PULS CC		; Status restaurieren
    	RTS		; und zurück

3.2/15

    ;
    ; Parametertabelle für Register
    ;
    TABLEN	FCB  #8		; 9 Eintragungen von 0 - 8
    REGPAR:	FDB  #$0077	; 1. Register: Kennung " A"
    	FCB  #0		; 0 = 1 Bytes
    	FDB  #$00F5	; Datum in $F5
    	FDB  #$007C	; 2. Register: Kennung " B"
    	FCB  #0		; 1 Byte
    	FDB  #$00F6	; Datum in $F6
    	FDB  #$0076	; 3. Register: Kennung " X"
    	FCB  #1		; 1 = 2 Bytes
    	FDB  #$00F8	; Datum in $F8/$F9
    	FDB  $006E	; 4. Register: Kennung " Y"
    	FCB  1		; 2 Bytes
    	FDB  $00FA	; Datum in $FA
    	FDB  $003E	; 5. Register: Kennung " U"
    	FCB  1		; 2 Bytes
    	FDB  $00FC	; Datum in $FC
    	FDB  $006D	; 6. Register: Kennung " S"
    	FCB  1		; 2 Bytes
    	FDB  $00F2	; Datum in $F2
    	FDB  $7358	; 7. Register: Kennung "PC"
    	FCB  1		; 2 Bytes
    	FDB  $00FE	; Datum in $FE
    	FDB  $5E73	; 8. Register: Kennung "DP"
    	FCB  0		; 1 Byte
    	FDB  $00F7	; Datum in $F7
    	FDB  $5858	; 9. Register: Kennung "CC"
    	FCB  0		; 1 Byte
    	FDB  $00F4	; Datum in $F4

Bild 3.2-9: Routine zum Editieren der Register

Praktische Übung P3.2-5:
Assemblieren Sie die Routine REGIST und testen Sie sie.

3.2/16

C. Laden und Sichern von Programmen und Datenbereichen

Der Monitor bietet mit den Routinen LOAD und SAVE die Möglichkeit, Programme und Daten über die V.24-Schnittstelle zu einem PC zu übertragen und dort auf der Festplatte oder einer Floppy Disk zu speichern 2). Diese Routinen gehören zu den aufwendigsten und umfangreichsten des Monitors. Wir wollen hier nur (eine mögliche Version für) die LOAD-Routine besprechen. (Die SAVE-Routine arbeitet analog dazu.)

Die Übertragung von Programmen und Daten erfolgt als ASCII-Zeichen im sogenannten Intel-Hex-Format, das im Bild 3.2-10 erklärt wird.

: | BA | ZAAH | ZAAL | ZK | DB1 | DB2 | DB3 | ... | DBBA | PS
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
: | 10 | 04 | 00 | 00 | BD | F1 | 10 | ... | 39 | 3F
: | 10 | 04 | 10 | 00 | 86 | 37 | CC | ... | 7E | F4
: | 10 | 04 | 20 | 00 | 8E | 00 | 20 | ... | 8E | BD
: | 02 | 04 | 30 | 00 | 35 | 39 | 5E | (Prüfsumme)
: | 00 | 00 | 00 | 01 | FF | (Prüfsumme)

Bild 3.2-10: Beispiel für eine Übertragung im Intel-Hex-Format

Die Übertragung in diesem Format ist zeilenweise orientiert. Jede Zeile beginnt mit dem Startzeichen ':' (ASCII-Code $3A). Danach folgt - wie alle anderen Daten in hexadezimaler Form - die Anzahl BA der in der Zeile übertragenen Datenbytes DBi. Es folgen zwei Bytes, die die Anfangsadresse ZAA (ZAAH,ZAAL) der übertragenen Datenzeile im Speicher angeben. Das nächste Byte ZK gibt durch ZK=$01 an, daß die letzte Zeile des Datenblockes übertragen wird. Alle vorherigen Zeilen werden durch ZK=$00 gekennzeichnet. Nach den Datenbytes DBi wird zum Abschluß jeder Zeile eine Prüfsumme PS übertragen, die als Zweierkomplement der 8-bit-Summe aller vorausgehenden Bytes der Zeile (außer der Kennung ':') berechnet wird.

Selbsttestaufgabe S3.2-3:
Welchen Wert berechnet der Empfänger einer Übertragung im Intel-Hex-Format als Summe über alle Bytes einer Zeile (außer der Kennung ':'), in der kein Übertragungsfehler aufgetreten ist ?

Bild 3.2-11 zeigt das Flußdiagramm der Routine Load. Nicht gezeigt ist die Initialisierung der V.24-Schnittstelle, die bereits nach dem Einschalten des Rechners (Power on Reset) oder nach jedem Betätigen der Funktionstaste C (Clear) durchgeführt wird 3). (Das Unterprogramm zum Empfang der übertragenen ASCII-Zeichen ist im Flußdiagramm 3.2-11 grau unterlegt dargestellt.)

Die empfangenen Daten werden im Programm LOAD vom ASCII-Code in die hexadezimale Form umgewandelt 4). Tritt dabei ein Fehler auf, wird die LOAD-Routine mit einer Fehlermeldung: 'FEhLEr hE' ('hE': Hexadezimal-Umwandlung) beendet. Eine Fehlermeldung: 'FEhLEr PS' ('PS': Prüfsumme) wird auch erzeugt, wenn die vom Empfänger neu berechnete Prüfsumme einen Übertragungsfehler anzeigt.

3.2/17

Praktische Übung P3.2-6:
Disassemblieren Sie - mit Hilfe des Programms DS9 - die LOAD-Routine (ab Adresse $FE00). Analysieren Sie das Programm und fügen Sie ausführliche Kommentare bei.

Bild 3.2-11: | Flußdiagramm der Routine LOAD 5) |

3.2/18

D. Ausführung der Anwenderprogramme

Zur Kontrolle der auf dem Rechner laufenden Programme gehört nicht nur der Start eines Programms, sondern genauso seine kontrollierte Beendigung. Zu diesem Zweck müssen geeignete Maßnahmen ergriffen werden, um den Rechner beim Start eines Programms in einen definierten Ausgangszustand zu versetzen und den Zustand des Systems bei der Beendigung oder beim Abbruch des Programms zu speichern, um später Rückschlüsse auf dessen Verhalten ziehen zu können. Insbesondere reicht es nicht aus, ein Anwenderprogramm durch einen Sprung zu seiner Startadresse zu aktivieren.

Der normale Programmstart geht folgendermaßen vor sich: Nachdem die Startadresse eingegeben und bei Bedarf ein Unterbrechungspunkt gesetzt wurde, setzt die GO-Routine den Stackpointer S auf den vorgewählten Wert und führt einen Software-Interrupt SWI2 aus. Damit werden die Inhalte aller Register des Prozessors (außer dem Stackpointer S) auf den Stapel gelegt und - da sie im Benutzerprogramm nicht benötigt werden - Platz für die Registerinhalte geschaffen, die vom Anwenderprogramm gebraucht werden. Diese werden nun aus dem Systembereich in den Stapel kopiert. Mit dem Befehl RTI holt der Prozessor nun alle Register vom Stapel, einschließlich des PC-Registers, das dann die Startadresse des Programms enthält.

Die Trace-Funktion ist eine der interessantesten Routinen des Monitors, deshalb geben wir sie in Bild 3.2-12 vollständig wieder - wenn auch in einer anderen als der im Monitor implementierten Form. Sie startet das Programm prinzipiell auf die gleiche Art und Weise wie die GO-Routine. Der wesentliche Unterschied zwischen beiden ist die Vorbereitung zur Unterbrechung des Programms nach der Ausführung eines einzigen Befehls.

Dazu wird der Zähler #2 des Timer-Bausteins MC6840 6) so eingestellt, daß während der Abarbeitung des ersten Programmbefehls eine NMI-Anforderung an der CPU eintrifft. Diese unterbricht daraufhin das laufende Programm am Ende des momentan ausgeführten Befehls, rettet alle Register auf den Stapel und verzweigt in die NMI-Routine.

Dort wird die Beendigung des Programms fortgesetzt: Die Registerinhalte werden vom Stapel in den Systembereich zurückkopiert, der Stackpointer auf den Wert vor dem Eintreffen des NMI zurückgesetzt und die entsprechende Meldung auf dem Display ausgegeben. Damit ist die TRACE-Routine beendet und der Monitor bereit, neue Aufgaben durchzuführen, z.B. die Inhalte der Register anzuzeigen etc.

Mit der vollständigen Beschreibung der TRACE-Routine haben Sie schon eine Methode kennengelernt, aus dem Anwenderprogramm in den Monitor zurückzukehren. Die beiden anderen Rückkehrroutinen, SWI1 zur Bearbeitung eines Breakpoints und die Taste F4 zum Abbruch eines Programms von der Tastatur aus, funktionieren grundsätzlich genauso, wobei zu beachten ist, daß die Taste F4 eine maskierbare Unterbrechungsanforderung IRQ erzeugt, die im Gegensatz zum nicht maskierbaren Interrupt NMI der TRACE-Routine nur dann ausgeführt wird, wenn der Interrupt nicht durch das Setzen des I-Flags im Statusregister der CPU blockiert wurde 7).

3.2/19

    ; Routine  TRACE: Einzelschrittausführung
    TI1CNT:	EQU  $F018
    TI2CNT:	EQU  $F019
    TI2MSB:	EQU  $F01C
    TI2LSB:	EQU  $F01D
    RECTAB:	EQU  $00F4
    PCREG:	EQU  $00FE
    CCREG:	EQU  $00F4
    TRACE:	SWI3		; Einen Programmbefehl ausführen
    ;	Hier wird nach dem NMI fortgefahren
    	LDA  TI2CNT	; NMI abschalten durch Lesen von St.Reg. 2
    	LDA  #$01	;
    	STA  TI1CNT	; Timer Reset, sperren
    	JSR  Kopie	; Registersatz vom Stack in Zero-Page kop.
    RETRAC:	JSR  CLRDISP	; Anzeige löschen
    	LDD  #$3150	; "Tr"
    	LDX  #6		;   im Operationsfeld
    	JSR  SHOWD	;   anzeigen
    TLOOP:	LDY  #PCREG	; Startadresse nach Y
    	LDB  ,Y		; zugehöriges Datum
    	LDX  #0		;   im Datenfeld
    	JSR  SHOWB7SG	;   anzeigen
    	LDX  #2		; im Adreßfeld
    	JSR  SHOWADR	;   Startadresse editieren
    	CMPB #$80	; zurück mit Taste '+' ?
    	BNE  +4		; falls nein, weiter
    	LEAY 1,Y	; Startadresse inkrementieren
    	BRA  TLOOP+4	; erneut editieren
    	CMPA #$81	; zurück mit Taste '-' ?
    	BNE  +4		; sonst zurück zur Hauptschleife
    	LEAY -1,Y	; Startadresse dekrementieren
    	BRA  TLOOP+4	; erneut editieren
    	LDB  ,Y		; Datum
    	LDX  #0		;   im Datenfeld
    	JSR  SHOWB7SG	;   anzeigen
    	STY  #PCREG	; neue Startadresse ablegen
    	LBRA MLOOP	; zurück zur Hauptschleife
    ; Start des Programms für TRACE
    SWI3:	LDA  <CCREG	; Statusregister
    	ORA   #$90	; E- und I-Flag setzen
    	STA <CCREG	; wieder ablegen
     ; Kopieren der Register vom Systembereich in den Stapel
    	TFR S,Y		; Y ist Ziel für die Register
    	LDX #REGTAB	; X ist die Quelle

3.2/20

    	LDB  #$C	; Länge der Tabelle
    	LDA  ,X+	; Datum holen
    	STA  ,Y+	;   und auf dem Stapel ablegen
    	DECB		; bis 12 Bytes kopiert,
    	BNE  -7		; wiederholen
    ; Timer setzen
    	LDA  #$C3	; Zähler #2, Interrupt zum NMI zulassen
    	STA  TI2CNT	; in Kontrollregister 2
    	CLRA		; 0 nach
    	STA  TI2MSB	;   Zähler #2, MSB-Buffer
    	LDA  #$D	; 13 nach
    	STA  TI2LSB	;   Zähler #2, LSB-Buffer
    	CLRA		; Reset abschalten,
    	STA  TI1CNT	; Zähler #2 läuft los
    	RTI		; Sprung in das Programm

Bild 3.2-12: Listing der TRACE-Routine

Selbsttestaufgabe S3.2-4:
Vergleichen Sie den Programmabbruch bei Erreichen eines Breakpoints (SWI) mit dem bei der Einzelschrittausführung (NMI). Wo liegt der wesentliche Unterschied ?

Die selbstprogrammierbaren Tastenfunktionen sind zwar mit den Routinen INSERT, DELETE und DUMP vorbelegt, können aber jederzeit auf eigene Routinen umgeleitet werden, indem die Startadresse in der Sprungtabelle des Kommandointerpreters gegen die Startadressen Ihrer eigenen Routinen ausgetauscht werden. Sie finden die entsprechenden Adressen bei der Beschreibung der Routinen in KE1.

Da der Kommandointerpreter, der die Routinen aktiviert, etwas anders arbeitet, als der in dieser Kurseinheit beschriebene, müssen Sie die Routinen mit dem Befehl JMP $E38F abschließen. Wie schon weiter vorn beschrieben, akzeptiert der Monitor einen eventuell schon im Akku B stehenden neuen Befehl nicht, der Rücksprung endet daher in der Tastaturabfrage des Monitors, und Sie müssen die gewünschte Funktionstaste noch einmal drücken.

Als Beispiel wollen wir die Taste F1 mit der Funktion FILLbelegen, die einen Speicherbereich zwischen zwei anzugebenden Bereichsgrenzen mit einem bestimmten Datum füllt. Wir benötigen dazu die Angaben über Bereichsanfang und Bereichsende und das Datum.

Für die Auswahl der Parameter verwenden wir praktischerweise die Routine, die auch zum Editieren der Register benutzt wird. Da sie gegenwärtig im Rechner nicht zur Verfügung steht, müssen wir sie selbst eintippen (Sie haben sie ja wahrscheinlich schon längst assembliert). Das Format der Tabelle entspricht ebenfalls exakt dem der vorgestellten Routine. Sie ist in Bild 3.2-13 dargestellt.

3.2/21

    ; Parametertabelle für FILL
    ;
    	ORG   $1800	; Startadresse der Tabelle
    TABLEN:	FCB  2		; Anzahl der Einträge -1
    FILPAR:	FDB   $7C77	; Bereichsanfangs-Kennung "bA"
    	FCB  1		; 2-byte-Datum
    	FDB   #BA	; bei Adresse $1810
    	FDB  $7C79	; Bereichsende-Kennung "bE"
    	FCB  1		; 2-byte-Datum
    	FDB  #BE	; bei Adresse $1812
    	FDB  $5E77	; Datums-Kennung "dA"
    	FCB  0		; 1-Byte-Datum
    	FDB  #DA	; bei Adresse $1814
    ;
    	ORG  $1810	; Daten für die FILL-Routine
    BA:	FDB  $400	; vorgegebener Bereichsanfang
    BE:	FDB  $4FF	; vorgegebenes Bereichsende
    DA:	FCB  $FF	; vorgegebenes Datum

Bild 3.2-13: Parametertabelle für die FILL Routine

Es fehlt noch die eigentliche Routine. Zunächst entwickeln wir das Flußdiagramm nach Bild 3.2-14:

Bild 3.2-14: | Das Flußdiagramm der FILL-Routine |

3.2/22

Damit gestaltet sich das Assemblerprogramm recht einfach. Dies ist im Bild 3.2-15 dargestellt.

    ; Routine FILL  (Taste F1)
    ;
    	ORG   $1820
    ;
    FILL:	PSHS  A,X,Y,CC	; Register retten
    	JSR   CLRDISP	; Anzeige löschen
    	LDD   #$7104	; 7-Segmentcode für "FI"
    	LDX   #6	;   im Operationsfeld
    	JSR   SHOWD	;   anzeigen
    	LDY   #FILPAR	; Y zeigt auf die Tabelle
    	CLRA		; ersten Parameter
    	JSR   EDIT	;   editieren
    	CMPB   #$89	; zurück mit F1?
    	BNE   R		; sonst Ende
    	LDX   BA	; Bereichsanfang in X
    	LDA   DA	; Datum in A
    LOOP:	STA   ,X+	;   in den Speicher schreiben
    	CMPX  BE	; Bereichsende erreicht ?
    	BNE    LOOP	; falls nein, wiederholen
    	STA   ,X	; letztes Datum schreiben
    	LDY   #$7954	; 7-Segment-Code für
    	LDD   #$5E79	;   "EndE" in Y und D
    	LDX   #2	;   im Adreßfeld
    	JSR   SHOWYD	;   anzeigen
    R:	PULS  A,X,Y,CC	; Register restaurieren
    	JMP   $E38F	; zurück zum Monitor

Bild 3.2-15: Die FILL-Routine in Assemblerschreibweise

Praktische Übung P3.2-7:
Assemblieren Sie das Programm und testen Sie es aus, indem Sie die Taste F1 neu belegen.

### 3.2.5 Interruptbehandlung

Oft muß ein Rechner auf Ereignisse reagieren, die unabhängig vom laufenden Programm ("asynchron") auftreten. Grundsätzlich gibt es hierzu zwei Möglichkeiten, das Auftreten dieser Ereignisse zu erkennen. Die erste besteht in der regelmäßigen Abfrage der Statusregister der angeschlossenen Peripheriebausteine auf ein solches Ereignis. Der Nachteil dieser Methode liegt auf der Hand: Das laufende Programm muß regelmäßig in eine entsprechende Routine springen, die die Peripherie auf Unterbrechungsanforderungen testet.

3.2/23

Diese Art der Programmierung ist nicht nur umständlich, in vielen Fällen sogar unmöglich, es wird auch ein großer Teil der Rechenkapazität des Prozessors auf Abfragen verschwendet, die nicht zu einer Unterbrechung führen. Außerdem kann es unter Umständen relativ lange dauern, bis auf die Unterbrechungsanforderung reagiert wird.

Aus diesem Grund besitzen Mikroprozessoren spezielle Eingangsleitungen, an die die Signale zur Unterbrechungsanforderung angelegt werden können. Der 6809-Prozessor stellt drei Leitungen für diese Signale zur Verfügung, die mit IRQ, FIRQ und NMI bezeichnet.

Die Arbeitsweise der Interrupts wurde im Einzelnen schon in KE1, Abschnitt 1.3.2, vorgestellt. Der Monitor benutzt zwei der drei Hardware-Interrupts, nämlich IRQ und NMI, und alle drei Software-Interrupts (SWI).

Zur Rückkehr aus einer Unterbrechung besitzt der Prozessor den speziellen Befehl RTI (ReTurn from Interrupt), der automatisch die zu Beginn der Unterbrechung gesicherten Register wieder vom Stapel holt. Er benutzt dazu das E-Bit des Statusregisters, das angibt, ob alle Register gerettet wurden (E = 1) oder nur die Register CC und PC.

Zurück zu den Hardwareunterbrechungen. Ein reales Computersystem kommt mit den drei zur Verfügung stehenden Interruptleitungen in der Regel bei weitem nicht aus. Selbst die Hardware des vergleichsweise kleinen Praktikumsrechners kann neun verschiedene Interrupts erzeugen, außerdem können extern weitere Geräte angeschlossen sein, die Unterbrechungsanforderungen an den Rechner schicken. Da jede dieser Anforderungen eine individuelle Behandlung verlangt, dem Prozessor aber nur drei Hardware-Interruptvektoren *) zur Verfügung stehen, ist es zunächst notwendig, die Herkunft eines Interrupts zu klären, um dann zu der speziellen Behandlungsroutine zu verzweigen. Diese Aufgabe wird von drei Auswertungsroutinen übernommen, die ebenfalls zum Monitorprogramm gehören und den drei Unterbrechungsleitungen zugeordnet sind. Die Startadressen der Auswertungsroutinen stehen in einem Stapel von µP-Vektoren, in dem auch der PC-Startwert und die SWI-Vektoren zu finden sind (s. KE1, Tabelle 1.3-1).

Am Beispiel der IRQ-Auswertungsroutine, deren Flußdiagramm Sie in Bild 3.2-16 finden, sehen Sie, wie das System funktioniert. Nacheinander werden die Peripheriebausteine daraufhin getestet, ob das Interrupt-Flag im Statusregister gesetzt ist und, falls ja, ob der Baustein den Interrupt auch an den Prozessor weitergeleitet hat. Das ist nötig, da es die Möglichkeit gibt, die Interrupt-Ausgangsleitung eines Peripheriebausteins abzuschalten,so daß ein im Statusregister angezeigter Interrupt gar nicht zum Prozessor weitergeleitet wird.

3.2/24

Die Abfrage wird fortgesetzt, bis die Quelle der Unterbrechung gefunden ist. Dann wird über eine Sprungtabelle, die sich im Systembereich befindet, die entsprechende Behandlungsroutine aufgerufen 1). Dadurch können Sie bei Bedarf eigene Routinen zur Bedienung der Unterbrechungen benutzen, indem Sie die Startadressen Ihrer eigenen Routinen in die Tabelle eintragen. Vom Monitor benutzt werden derzeit nur der IRQ über den Eingang CA1 von Port A des Parallel-Schnittstellenbausteins MC6821 2), der das Signal der BREAK-Taste weiterleitet, und der NMI von Zähler #2 von Baustein MC6840 für die TRACE-Funktion. Alle anderen Vektoren zeigen auf die Adresse $E643E und damit auf den Befehl RTI ($39), der unter dieser Adresse abgespeichert ist.

Für den Fall, daß mehrere Geräte an den Bus angeschlossen sind, die den gleichen Interrupt auslösen können, hat der Benutzer dafür Sorge zu tragen, daß der Vektor für eine Unterbrechung von außerhalb des Rechners auf eine weitere Auswertungsroutine zeigt, die nach oben dargestelltem Verfahren das auslösende Gerät ermittelt und die weitere Ausführung einleitet.

Bild 3.2-16: | Flußdiagramm der Routine zur Auswertung des IRQs |

3.2/25

In der Interrupt-Vektorentabelle finden sich imübrigen auch die Startadressen der SWI-Routinen, die alle drei vom Monitor benutzt werden: SWI1 kennzeichnet einen Breakpoint im Anwenderprogramm, SWI2 führt den Programmstart und SWI3 die TRACE-Funktion durch. Um Ihnen die Möglichkeit zu geben, wenigstens SWI2 und SWI3 ebenfalls zu benutzen, werden auch diese auf ihren Ursprung hin untersucht: Durch die Abfrage der Rücksprungadresse auf dem Stapel wird festgestellt, ob der SWI aus dem RAM- oder ROM-Bereich kam. Ist sie kleiner als $8000, handelt es sich um einen vom Benutzer erzeugten SWI, anderenfalls wurde er vom Monitor ausgelöst.

Zum Abschluß wollen wir Ihnen noch ein typisches Beispiel für den Unterschied zwischen der Abarbeitung einer Routine mit wiederholter Abfrage eines Bausteins oder per Interrupt geben: Die Ausgabe einer Zeichenkette an die serielle Schnittstelle. Beide Flußdiagramme sind in Bild 3.2-17 und Bild 3.2-18 dargestellt. Während im ersten Fall der Prozessor während der gesamten Übertragungszeit mit der Ausgabe beschäftigt und damit für andere Aufgaben blockiert ist, wird er bei der zweiten Methode jeweils nur für wenige Mikrosekunden für die Ausgabe eines Zeichens beansprucht und ist während der restlichen Zeit für andere Aufgaben verfügbar 3).

Bild 3.2-17: | Ausgabe mit zyklischer Abfrage des Statusregisters |

3.2/26

Bild 3.2-18: | Ausgabe mit Interruptsteuerung |

| 3. Aufbau Praktikumsrechner & Betriebssoftware |  | Lösungsvorschläge zu den Praktischen Übungen |