Magic Disk 64

home to index to text: MD9311-KURSE-IRQ-KURS_1.2.txt

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)

Valid HTML 4.0 Transitional Valid CSS!