Assembler-Kurs Teil 10
Wie versprochen, handelt der letzte Teil
dieses Kurses von en Interrupts.
Interrupt bedeutet soviel wie "Unter-
brechung" des laufenden Programms. Der
C64 reagiert auf verschiedene Arten von
Interrupts, die man in Hard- und Soft-
wareinterrups unterteilen kann.
Hardware-Interrupts
-------------------
Es gibt zwei unterschiedliche Arten von
Hardware-Interrupts, den IRQ (interrupt
request = Interrupt Anforderung) und den
NMI (non maskable interrupt = Nicht
maskierbarer Interrupt). Beide sind
eigentlich Pins am Prozessor, an denen
durch ein Impuls ein entsprechender
Interrupt ausgelöst werden kann. Die
Reaktion des Prozessors auf beide
Interrupts ist etwas unterschiedlich.
Grundsätzlich sagt man, daß der NMI die
höhere Priorität beider Interrupt-Arten
hat und somit für die für das System
wichtigen Aufgaben eingesetzt wird.
a) Ablauf eines NMI:
1.Der momentan zu bearbeitende Befehl
des laufenden Programms wird noch
ausgeführt.
2.Der Programmzähler (program
counter), d.h. das Register, das
immer auf den nachfolgenden Befehl
eines Programms zeigt, wird auf den
Stack geschoben. Dabei wird zuerst
das höherwertige und dann das
niederwertige Byte des Programm-
zählers abgelegt.
3.Das Statusregister, das alle Flags
enthält, wird auf den Stack
gebracht.
4.Der Inhalt der Adressen $FFFA (als
niederwertiges Byte) und $FFFB (als
höherwertiges Byte) wird zusammen-
gesetzt und als neuer Programm-
zähler benutzt. Ab jetzt wird also
das (unterbrechende) Programm an
der Stelle ausgeführt, auf die der
neue Programmzähler zeigt.
b) Ablauf eines IRQ:
1.Zunächst scheint der IRQ genauso
zu verlaufen, wie der NMI. Der
augenblicklich zu bearbeitende
Befehl des laufenden Programms wird
noch vollständig abgearbeitet.
2.Anschließend erfolgt eine
Überprüfung des Interrupt-Flags
(Bit 2 des Statusregisters). Wenn
das Bit gesetzt ist, dann wird die
Interrupt-Anforderung einfach
ignoriert, und der Prozessor fährt
fort, als ob nichts geschehen wäre.
Ist das Interrupt-Bit jedoch
gelöscht, so wird der IRQ
ausgeführt.
3.Der Programmzähler wird auf den
Stack geschrieben.
4.Das Statusregister wird gestackt.
5.Nun wird das Interrupt-Flag
gesetzt, so daß alle nachfolgenden
Interrupt-Anforderungen ignoriert
werden. Man bezeichnet diesen
Vorgang als 'Sperren' des IRQ.
6.Der Inhalt der Adressen $FFFE und
$FFFF wird zusammengesetzt und als
neuer Programmzähler benutzt.
Der Hauptunterschied zwischen NMI und
IRQ liegt darin, daß der IRQ maskiert
(d.h. gesperrt) werden kann.
Wie oben bereits beschrieben, wird beim
IRQ zuerst das I-Flag untersucht und
erst daraufhin entschieden, ob ein
Interrupt auszuführen ist, oder nicht.
Dieses Interrupt-Flag des maskierten
Interrupts IRQ kann vom Programmierer
selbst direkt beeinflußt werden.
Mit dem Befehl SEI (SEt Interrupt mask)
wird das I-Flag gesetzt und somit werden
alle folgenden IRQs gesperrt. Durch CLI
(CLear Interrupt mask) kann dieser
Zustand wieder aufgehoben werden,indem
das I-Flag gelöscht wird. Ein IRQ ist
nun für den nachfolgenden Programmteil
wieder zugelassen. Häufige Anwendung
finden diese beiden Befehle auch beim
Umschalten der Speicherkonfiguration
durch den Prozessorport. Ohne das
vorherige Abschalten der Interrupts
mittels SEI kann es beim Ausschalten von
ROM-Berichen zum Systemabsturz kommen.
Wodurch können die Interrupt IRQ und NMI
ausgelöst werden ?
Selbstverständlich nur durch die Hard-
ware des Computers:
IRQ: a) durch den Videocontroller VIC
b) durch den CIA-Baustein ($DC00)
NMI: a) durch den CIA-Baustein ($DD00)
b) durch die RESTORE-Taste
Der Software-Interrupt
----------------------
Software-Interrupts werden durch den
Befehl BRK (BReaK) ausgelöst. Das war
einer der ersten Befehle, die wir in
diesem Kurs kennengelernt haben. Nun
wollen wir untersuchen, was genau
passiert, wenn der Prozessor auf einen
BRK-Befehl im Programm stößt:
1.Das Break-Flag (Bit 4 des Status-
registers) wird gesetzt.
2.Der Programmzähler wird auf den Stack
gebracht.
3.Das Statusregister wird gestackt.
4.Nun wird das Interrupt-Flag gesetzt,
so daß alle IRQs gesperrt werden.
5.Der Inhalt der Adressen $FFFE und
$FFFF (dieselben Adressen wie beim
IRQ) wird zusammengesetzt und als
neuer Programmzähler benutzt.
Meistens wird der BRK-Interrupt von den
Assembler-Monitoren dazu genutzt, um das
laufende Programm abzubrechen und das
Statusregister mit den aktuellen Flags
anzuzeigen. Es wäre aber auch eine
andere Nutzung dieses Interrupts
möglich.
Der Software-Interrupt BRK wird also
im Gegensatz zu den Hardware-Interrupts
durch einen Assembler-Befehl ausgelöst.
Egal, ob IRQ, NMI oder der Software-
interrupt BRK. Eines haben alle
gemeinsam. Sie lesen alle einen Zeiger
aus ($FFFE/FFFF bei IRQ,BRQ; $FFFA/$FFFB
bei NMI) der auf eine ROM-Routine weist.
Diese ROM-Routinen werden nun als
Interruptprogramm abgearbeitet und
führen am Ende einen unbedingten Sprung
aus. Dieser unbedingt e Sprung beruft
sich auf einen Zeiger, der im RAM steht.
Diese Zeiger sind: für IRQ $0314/$0315
für BRK $0316/$0317
für NMI $0318/$0319
Diese Zeiger sind schon mit einem
bestimmten Wert initialisiert, so daß
der Sprung ohne unser Eingreifen bestens
funktioniert. Wie Sie schon ahnen
werden, müssen wir diesen Zeiger
lediglich auf unsere selbstgeschriebenen
Routinen umbiegen, und schon haben wir
eigene Interruptroutinen.
Das Ende der Interrupts: RTI
----------------------------
Wenn das Programm durch einen Interrupt
unterbrochen wurde und der Prozessor nun
eine Interrupt-Routine bearbeitet, dann
muß ihm auch irgendwie kenntlich gemacht
werden, wann diese Unterbrechung beendet
werden soll. Auch die Interruptroutinen
benötigen daher ein Programmende. Für
'normale' Programme haben wir als
Kennzeichnung für das Programmende immer
den RTS-Befehl (ohne vorherigen
JSR-Befehl) im Hauptprogramm benutzt,
wodurch wir zurück ins BASIC kamen.
Der Befehl für das Ende unser selbstge-
schriebenen Interrupt-Routine lautet RTI
(ReTurn from Interrupt). Bei der Bear-
beitung dieses Befehls läuft der
umgekehrte Prozeß des Interrupt-Aufrufs
ab.
1.Das Statusregister muß vom Stack
geholt werden.
2.Der Programmzähler wird vom Stack
geholt und wieder als aktueller
Zähler benutzt.
3.An der Stelle, auf die der Programm-
zähler zeigt, wird das unterbrochene
Programm fortgeführt.
Der Hauptunterschied zwischen RTS und
RTI liegt darin, daß beim RTI zusätzlich
zum Programmzähler auch noch das Status-
register vom Stack geholt werden muß.
Ein Interrupt hat doch einige Ähnlich-
keiten mit einem Unterprogrammaufruf.
Ein Unterprogramm wird jedoch von einer
klar definierten Stelle im Hauptprogramm
(durch den JSR-Befehl) aufgerufen. Die
Interrupts NMI und IRQ werden jedoch
hardwaremäßig ausgelöst, so daß die
Unterbrechung des Hauptprogramms an
jeder beliebigen Stelle stattfinden
kann. Diese Eigenschaft erweckt den
Eindruck, daß die Interruptroutine und
das Hauptprogramm parallel arbeiten, was
aber natürlich nicht der Fall ist.
In dem Begleitprogramm
"ASSEMBLER-KURS10"
werden wir eigene Interrupt-Routinen
schreiben. Dabei geht es um die
Benutzung des Systeminterrupts und der
Interrupts durch den Videocontroller
(Rasterzeilen-Interrupt).
Dies war der letzte Teil des Assembler-
Kurses. Ich hoffe, er konnte Ihnen
einige Kenntnisse und Anregungen
verschaffen.
rt/wk