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.