Um bei JEDEM BRK wieder in einen definierten Zustand zu gelangen, müssten wir
das unterbrochene Programm gänzlich
stoppen und anschließend wieder zur BA-SIC- Eingabe zurückkehren. Dies ist eine
sehr einfache Öbung. Wir müssen lediglich den " Müll" den Prozessor und Betriebssystem- BRK-Routine auf dem Stapel
abgelegt haben, mit Hilfe von sechs aufeinanderfolgenden " PLA"- Befehlen von
dort wieder wegholen, und anschließend
einen BASIC-Warmstart durchführen. Noch
einfacher und sauberer geht es jedoch, wenn wir den Stapelzeiger gleich nochmal
neu initialisieren. Hierbei werden nämlich auch nicht mehr benötigte Daten, die evtl. vor Auslösen des Interrupts
auf dem Stack abgelegt wurden, entfernt.
Demnach kann jedes Programm mit folgendem Interrupt abgebrochen werden:
LDX #$ FF ; Stapelzeiger per X-Register TXS ; zurücksetzen JMP $ E386 ; BASIC-Warmstart anspringen.
Es ist ein beliebiges Programm daß immer
am Ende eines Interrupts stehen kann. Es
bricht zusätzlich auch den Interrupt ab
und kehrt zur BASIC-Eingabe zurück.
Folgendes Programmbeispiel nutzt diese
Methode. Zuvor holt es sich jedoch die
vom Interrupt auf dem Stapel abgelegten
Informationen, und gibt Sie in hexadezimaler Schreibweise auf dem Bildschirm
aus. Dadurch haben Sie eine ganz simple
Debugging-Kontrolle, mit der Sie Fehler
in eigenen Programmen abfangen können.
Wird z. B. ein bestimmter Programmteil
angesprungen, der einen BRK-Befehl
enthält, so wird diese Routine angesprungen, die Ihnen die Registerinhalte, sowie Zustand des Programmzählers, des
Statusregisters und des Stapelzeigers
zum Zeitpunkt der Unterbrechung auf dem
Bildschirm ausgibt. Hier das Listing:
;*** Hauptprogramm
1000: LDX #$0B ;BRK-Vektor auf 1002: LDY #$10 ; eigene Routine 1004: STX $0316 ; bei $100B 1007: STY $0317 ; verbiegen 100A: BRK ;Interrupt auslösen ;*** Interruptroutine 100B: LDA #$69 ;Adresse Infotext 100D: LDY #$10 ; ($1069) laden 100F: JSR $AB1E ;Text ausgeben 1012: PLA ;Inhalt Y-Register 1013: JSR $103E ; ausgeben 1016: PLA ;Inhalt X-Register 1017: JSR $103E ; ausgeben 101A: PLA ;Akkuinhalt 101B: JSR $103E ; ausgeben 101E: PLA ;Statusregister 101F: JSR $103E ; ausgeben 1022: PLA ;PC Low-Byte holen 1023: STA $02 ; u. zwischenspeich. 1025: PLA ;PC High-Byte holen 1026: JSR $103E ; u. ausgeben 1029: LDA #$9D ;'CRSR' left 102B: JSR $FFD2 ; ausgeben 102E: LDA $02 ;PC Low-Byte holen 1030: JSR $103E ; u. ausgeben 1033: TSX ;Stapelzähler nach 1034: TXA ; Akku übertragen 1035: JSR $103E ; u. ausgeben 1038: LDX #$FF ;Stapelzähler 103A: TXS ; initialiseren 103B: JMP $E386 ;BASIC-Warmstart
Im Bereich von $1000-$1009 setzen wir, wie gewohnt, den BRK-Interruptvektor auf
den Beginn unserer Routine, der in diesem Beispiel bei $100 B liegt. In $100 A
wird ein BRK ausgelöst, der die Interruptroutine sofort anspringt. Diese gibt
nun, mit Hilfe der Betriebssystemroutine
" STROUT" bei $ AB1 E, einen kleinen Infotext auf dem Bildschirm aus. Hiernach
holen wir uns Yund X-Register, sowie
Akku und Statusregister vom Stapel ( in
dieser Reihenfolge), und zwar in dem
Zustand, den sie zum Zeitpunkt, als die
Unterbrechung eintrat, innehatten. Die
Werte werden dabei einzeln mit der Rou- tine bei $103 E auf dem Bildschirm ausgegeben. Diese Routine wandelt den Akkuinhalt in eine hexadezimale Zahl um, die
auf dem Bildschirm angezeigt wird. Hinter dieser Zahl gibt sie zusätzlich ein
Leezeichen aus, das als optische Trennung zwischen diesem, und dem nächsten
Wert dienen soll. Die genaue Beschreibung erspare ich mir hier, da sie ja
eigentlich nichts mit unseren Interrupts
zu tun hat.
Im Bereich von $1022-$1032 wird nun
zunächst das Low-Byte des alten Programmzählers vom Stapel geholt und in
der Speicherzelle $02 zwischengespeichert. Hieraufhin wird das High-Byte
geladen und auf dem Bildschirm ausgegeben. Abschließend wird das Low-Byte wieder aus $02 herausgeholt und ebenfalls
ausgegeben. Zwischen den beiden Zahlen
schicken wir noch ein ' CRSR links'- Zeichen auf den Bildschirm, da das Leezeichen, das durch unsere Ausgaberoutine
zwischen Highund Lowbyte steht, nicht erscheinen soll. Die beiden Werte sollen
ja zusammenhängend ausgeben werden.
Abschließend wird der Stapelzeiger in
den Akku transferiert und ebenfalls ausgegeben. Da wir zu diesem Zeitpunkt ja
schon alle Daten, die durch den Interrupt auf den Stapel gelegt wurden, wieder von dort entfernt haben, entspricht
der Stapelzeiger genau dem Wert, der zum
Zeitpunkt der Unterbrechung vorhanden
war.
Abschließend wird der Stapelzeiger wie
oben beschrieben zurückgesetzt, und das
Programm verzweigt auf den BASIC-Warm- start, womit wir den Interrupt ohne Verwendung von " RTI", unter Korrektur aller
ggf. erfolgten Änderungen am Stapel, verlassen hätten.
Versuchen Sie doch jetzt einmal BRKs von
anderen Adressen aus ( durch " POKE Adresse,0 : SYS Adresse", oder in eigenen Programmen auszulösen. Sie werden hierbei
immer wieder zu unserer kleinen Registeranzeige gelangen, die das System automatisch wieder ins BASIC zurückführt. Benutzen Sie jedoch nach dem
erstmaligen Initialiseren des Programms
nach Möglichkeit keinen Speichermonitor
mehr, da diese Hilfsprogramme nämlich
ähnlich arbeiten wie unser Programm, und
somit den von uns eingestellten BRK-Vektor auf ihre eigenen Routinen verbiegen.
Experimentieren Sie einmal ein wenig mit
den BRK-Unterbrechungen, um sich die
Eigenarten von Interrupts im Algmeinen
anzueignen. Im nächsten Kursteil werden
wir uns dann um die Ansteuerung der NMIund IRQ-Unterbrechungen kümmern, bevor
wir uns dann im dritten Teil endlich den
interessantesten Interrupts, den Raster-IRQs nämlich, zuwenden werden.
(ub/ih)