CIA-Kurs:
"Die Geheimnisse des Secret Service..."
(Teil 2)
----------------------------------------
Herzlich willkommen zur zweiten Runde
unseres CIA-Kurses. Nachdem ich Sie
letzten Monat ja lange genug mit der
trockenen Theorie von der Bedienung der
Timer der CIAs gelangweilt habe, will
ich jetzt einmal den Grundstein zur Pra-
xis legen. Ich möchte mich diesmal mit
dem eigentlichen Ablauf eines Interrupts
beschäftigen und Ihnen einen solchen
auch haarfitzelgenau anhand des System-
interrupts erklären.
1) Der Prozessor und ein Interrupt.
-----------------------------------
Wie ich schon im letzten Teil erwähnte,
wird der Systeminterrupt vom Betriebs
system des 64ers zur Erledigung ver-
schiedener zyklischer Aufgaben genutzt.
Er wird 60 mal in der Sekunde aufgerufen
und von Timer A der CIA1 erzeugt. Dem-
nach haben wir also einen IRQ (wir erin-
nern uns: CIA1 erzeugt Impulse an der
IRQ-Leitung des Prozsessors, CIA2 an der
NMI-Leitung). Die Timerregister TALO und
TAHI beinhalten die Werte 37 und 64. Der
Timer zählt also von 16421 (=HI*256+LO)
bis 0 herunter und löst dann einen In-
terrupt aus. Das ist auch ganz logisch,
denn wenn wir ja 60 Interrupts in der
Sekunde haben wollen, dann müssen wir ja
den Systemtakt durch 60 dividieren. Das
Ergebnis hiervon ist 16420.8, aufgerun-
det 16421! Ich hoffe Sie verstehen
jetzt, warum ich mich zunächst um die
Timer selbst gekümmert hatte, da Sie nun
auch besseren Einblick in den Systemin-
terrupt haben. Wenn Sie einmal ein bis-
schen rumprobieren möchten, bitte:
Schreiben Sie doch einfach einmal mit-
tels POKE einen höheren oder niedrigeren
Wert als 64 in TAHI (Reg. 5 von CIA1).
Das Ergebnis sehen Sie dann am Cursor-
blinken, was ebenfalls vom Systeminter-
rupt erledigt wird. Der Cursor sollte
nun entweder schneller (bei niedrigerem
Wert) oder langsamer (bei höherem Wert)
blinken. Übertreiben Sie die Werte je-
doch nicht übermäßig, da auch die Tasta-
turabfrage vom Systeminterrupt erledigt
wird, und Sie so entweder einen Turbo-
Cursor haben, mit dem bei eingeschalte-
tem Key-Repeat (das ist bei meinem
Floppy-Speeder-Betriebssystem nämlich
der Fall, und ich bin eben beim Auspro-
bieren natürlich prompt wieder darauf
hereingefallen...) keine vernünftigen
Eingaben gemacht werden können, ebenso
wie bei einem ultralangsamen Cursor, wo
es noch bis morgen dauern würde, einen
rücksetzenden POKE-Befehl einzugeben.
Dieser Trick wird übrigens oft benutzt,
um Programme schneller zu machen. Je
öfter nämlich ein Interrupt pro Sekunde
auftritt, desto weniger Zeit hat der
Prozessor, das momentan laufende Haupt-
programm abzuarbeiten. Setzt man jedoch
die Zahl der Interrupts pro Sekunde he-
runter, oder schaltet man ihn sogar ganz
ab (indem man den Timer einfach anhält,
oder mittels des Assemblerbefehls SEI
Interrupts ganz sperrt), so läuft das
Hauptprogramm logischerweise schneller
ab. Dies nur ein Tip am Rande.
Was geht nun eigentlich in unserem 64er
vor, wenn ein Interrupt abgearbeitet
werden soll? Nun, zunächst einmal haben
wir da einen Unterlauf von Timer A der
CIA1. Diese legt sodann auch gleich ein
Signal an die IRQ-Leitung des Prozessors
an und markiert die Interruptquelle "Ti-
mer A" in ihrem ICR.
Folgende Prozesse gehen nun im Prozessor
vor:
1) Der Prozessor überprüft nun nach je-
dem abgearbeiteten Befehl den Zustand
der Unterbrechungsleitungen (IRQ,
NMI). Ist eine davon gesetzt, und ist
der zugehörige Interrupt auch freige-
geben, so beginnt er damit, die Un-
terbrechung zu bearbeiten. Hierzu
müssen zunächst die wichtigsten Daten
auf den Stapel gerettet werden. Das
sind in der hier gezeigten Reihenfol-
ge:
* HI-BYTE des Programmzählers
* LO-BYTE des Programmzählers
* Prozessorstatusregister
Der Programmzähler ist ein Prozessor-
internes Register, das anzeigt, an
welcher Speicheradresse, der nächste
zu bearbeitende Befehl liegt. Das
Prozessorstatusregister beinhaltet
die Flaggen, die dem Prozessor bei
Entscheidungen weiterhelfen (ich ver-
weise da auf die letzten Kursteile
des Assemblerkurses meines Kollegen
RALF TRABHARDT).
2) Der Prozessor setzt sich selbst das
Interrupt-Flag und verhindert so,
daß er durch weitere Interrupts
gestört wird.
3) Ganz am Ende des Speichers (in den
Adressen $FFFA-$FFFF) sind 6 Bytes
für das Interrupt-Handling reser-
viert. Dort stehen insgesamt 3 Vekto-
ren, die dem Prozessor zeigen, bei
welcher Unterbrechung er wohin sprin-
gen muß, um einen Interrupt zu bear-
beiten. Diese Vektoren heißen im
Fachjargon übrigens auch Hardware-
Vektoren. Hier einmal eine Aufli-
stung:
Interrupt Vektor Adresse
-------------------------------------
NMI $FFFA/$FFFB $FE43 (65091)
RESET $FFFC/$FFFD $FCE2 (64738)
IRQ,BRK $FFFE/$FFFF $FF48 (65352)
Da wir ja einen IRQ behandeln, holt
sich der Prozessor jetzt also die
Adresse, auf die der Vektor in
$FFFE/$FFFF zeigt in den Programmzäh-
ler und beginnt so damit eine Jobrou-
tine für den IRQ abzuarbeiten.
Diese Jobroutine wollen wir uns jetzt
einmal genauer ansehen. Vorher jedoch
noch eine kleine Erläuterung. Wie Sie ja
sehen, wird der Vektor für den IRQ auch
als Vektor für BRK-Unterbrechungen be-
nutzt. Der BRK-Befehl sollte Ihnen ja
vielleicht bekannt sein (wenn Sie sich
mit Maschinensprache auskennen). Er hat
ansich ja keinen direkten Verwendungs-
zweck, jedoch wird er von vielen Moni-
tor-Programmen zum Debuggen benutzt. Wie
Sie ebenfalls sehen können, hat er glei-
che Priorität wie ein IRQ, und man kann
Ihn also auch als eigenen Interrupt an-
sehen. Vielmehr ist der BRK-Befehl die
Unterbrechungsquelle für BRK-Interrupts.
Wie man mit ihm umgeht, will ich Ihnen
später zeigen.
Werfen wir nun jedoch einmal einen Blick
auf die Jobroutine ab $FF48 - diese be-
findet sich natürlich im Betriebssystem-
ROM, weshalb ich Ihnen hier auch einen
Auszug daraus liefern möchte (ich habe
dies in Form einer Grafik getan, damit
ich ausführlichere Kommentare zu den
einzelnen Programmschritten geben kann).
Bitte laden Sie hierzu den 2. Teil des
CIA-Kurses.