Memory Map mit Wandervorschlägen Teil 18 (Schluß)

Bei der Wanderung durch die Speicherlandschaft erreichen wir heute unser Ziel, die Speicherzelle 1023. In diesem letzten Teil werden alle indirekten Sprungvektoren für das Betriebssystem behandelt.

Heute sind die indirekten Sprungvektoren auf Routinen des Betriebssystems an der Reihe, gefolgt vom Kasstettenpuffer. Das alles bringt uns ans Ziel der Reise durch die Speicherlandschaft.

Adresse 788 bis 789 ($314 bis $315)

Vektor auf die IRQ-Interrupt-Routine des Betriebssystems

Dieser Vektor zeigt auf die Adresse 59953 ($EA31) — beim VC 20 auf 60095 ($EABF). Ab hier beginnt die Routine des Betriebssystems, die den IRQ-Interrupt ausführt. Die Bedeutung der verschiedenen Interrupts (Unterbrechungen), ihre Auslöser und Abläufe sind als Übersicht im Texteinschub »Dem Computer ins Wort fallen« dargestellt.

Die IRQ-Routine wird vom Timer A des Ein-/Ausgabe-Bausteins CIA # 1 — beim VC 20 vom Timer 1 des Ein-/Ausgabe-Bausteins VIA # 2 — ausgelöst, und zwar periodisch 60mal in jeder • Sekunde. In der Programmpause werden die im Texteinschub beschriebenen »Haushaltsarbeiten« durchgeführt.

Dieser Vektor eignet sich hervorragend für eigene Programmierzwecke, da er durch das Verbiegen auf eine andere Adresse seine gleichmäßige und hochfrequente Wiederkehr nicht verliert. Mit seiner Hilfe können also eigene Maschinenprogramme 60mal in der Sekunde in ein Programm eingeschoben werden — eine Methode, die deswegen den englischen Namen »Wedge« = Keil erhalten hat. Zwei Vorbedingungen sind allerdings dabei zu erfüllen.

  1. Da ein IRQ mit Sicherheit während des Verbiegens auftritt, muß er vorher abgeschaltet werden. Den Schlüssel dazu bietet die Speicherzelle 56334, die mit 0 gePOKEt den Interrupt abschaltet und mit POKE 56334,1 ihn wieder zuläßt. Beim VC 20 ist dies POKE 37116,127 beziehungsweise POKE 37116,192. Aber Vorsicht!! Da während eines IRQ-Interrupts auch die Tastatur abgefragt wird, kann das Abschalten nur innerhalb eines Programms erfolgen — während der Abschaltung ist die Tastatur tot.
  2. Am Ende eines »Wedge« muß der Sprung auf die alte IRQ-Adresse erfolgen, die ursprünglich in den Speicherzellen 788 bis 789 stand, damit — etwas verspätet zwar — die normalen Haushaltsarbeiten des IRQ nachgeholt werden können. Bei längeren Wedges wird daher die interne Uhr TI und TI$ etwas nachgehen.

Ich habe lange nach einem Beispiel gesucht. Ich kenne viele: Abfrage der Joysticks, Lautstärke von Tönen mit Funktionstasten steuern, von Basic unabhängige Laufschrift, um ein paar zu nennen. Aber alle haben einen ziemlich langen Maschinensprache-Teil. Ich bringe daher hier das kürzeste Beispiel, das ich kenne. Es stammt aus dem CHIP-Sonderheft »C 64 PEEK + POKE Adreßbuch« von Rügheimer und Spanik.

Das Programm verändert dauernd die Farbe des Bildschirmrahmens:

10 FOR K=679 TO 699
20 READ A
30 POKE K,A:NEXT
40 DATA 166,162,224,0,224,128,240
50 DATA 3,76,49,234,174,32,208
60 DATA 202,142,32,208,76,175,02
70 POKE 56334,0
80 POKE 788,167:POKE 789,2
90 POKE 56334,1

Dieses Programm gilt nur für den C 64; für den VC 20 müßte es entsprechend umgeschrieben werden.

Die Zeilen 10 bis 30 lesen das Maschinenprogramm, das in den DATA-Zeilen 40 bis 60 steht, in die Speicherzellen 679 bis 699. Diese stehen, wie wir das letzte Mal gesehen haben, zur freien Verfügung — und sind daher ideal geeignet, ein kleines Maschinenprogramm ungestört aufzunehmen.

In Zeile 70 wird der IRQ-Interrupt unterbrochen. Jetzt kommt der wichtige Teil: Zeile 80 verbiegt den IRQ-Vektor zur Speicherzelle 176 + 256 * 2 = 679. Zeile 90 schaltet schließlich den IRQ-Interrupt wieder ein.

Jetzt passiert also folgendes: Jedesmal, wenn der Timer A den Haushalt-IRQ auslöst, springt der Computer zuerst einmal auf das Maschinenprogramm ab Speicherzelle 679 und schaltet die Rahmenfarbe um. Dann erst springt der letzte Befehl des Maschinenprogramms auf die ursprüngliche IRQ-Adresse 59953 ($EA31), von der aus das Betriebssystem weitermacht, als sei nichts geschehen.

Für Kenner gebe ich noch das Assembler-Listing des Maschinenprogramms an:

,02A7  A6 A2     LDX A2
,02A9  E0 00     CPX #00
,02AB  E0 80     CPX #80
,02AD  F0 03     BEQ 02B2
,02AF  4C 31 EA  JMP EA31
,02B2  AE 20 D0  LDX D020
,02B5  CA        DEX
,02B6  8E 20 D0  STX D020
,02B9  4c Af 02  JMP 02AF

Es gibt noch eine kleine, erwähnenswerte Anwendung. Wenn der Vektor nicht auf den Anfang der IRQ-Routine bei 59953, sondern auf 59956 — also drei Stellen weiter — zeigt, übergeht die IRQ-Routine den Teil, welcher die STOP-Taste abfragt und die TI/TI$-Uhr weiterschaltet, wodurch effektiv die STOP-Taste ausgeschaltet wird. Das geht ganz schnell mit POKE 788,52. Mit POKE 788,49 wird das wieder rückgängig gemacht. Beim VC 20 sind es die Werte POKE 788,194 oder POKE 788,191.

Adresse 790 bis 791 ($316 bis $317)

Vektor auf die BREAK-Interrupt-Routine des Betriebssystems

Diese Routine ist im Texteinschub nicht erwähnt, weil sie ein Teil der NMI-Routine ist. Dieser Vektor zeigt auf die Adresse 65126 ($FE66) - beim VC 20 auf 65234 ($FED2). Die da beginnende Routine des Betriebssystems wird aufgerufen, wenn der Maschinenbefehl BRK ausgeführt wird. Er führt letztlich zu einem Warmstart, das heißt der Bildschirm wird gelöscht und der Cursor meldet sich mit READY. Diese Routine wird auch durch das gleichzeitige Drücken der STOP- und der RESTORE-Taste angestoßen.

Adresse 702 bis 793 ($318 bis $319)

Vektor auf die NMI-Routine des Betriebssystems.

Der NMI-Interrupt ist im Texteinschub »Dem Computer ins Wort fallen« näher beschrieben. Der Vektor zeigt auf den Beginn dieser Routine ab Speicherzelle 65095 ($FE4 7) - beim VC 20 ab 65197 ($FEAD).

Sobald ein NMI-Interrupt auftritt, wird zuerst durch Setzen der Interrupt-Abschalt-Flagge (Interrupt Disable Flag)jede Unterbrechung durch den IRQ-Interrupt unterbunden. Dann wird geprüft, wer den NMI-Interrupt ausgelöst hat, und zwar in der Reihenfolge: RS232-Schnittstelle, RESTORE-Taste; eingestecktes Modul und schließlich die STOP-Taste. Die letztere dient zum Sichern der RESTORE-Taste. Nur wenn beide gemeinsam gedrückt werden, kommt die NMI-Unterbrechung durch die RESTORE-Taste zur Auswirkung.

Da die RESTORE-Taste fast als erste abgefragt wird, kann sie und ihre Kombination mit der STOP-Taste durch Verbiegen des Vektors in Speicherzelle 792 bis 793 abgeschaltet werden. Beim C 64 geht das mit POKE 792,193. Wieder eingeschaltet wird mit POKE 792,71. Beim VC 20 geht das mit POKE 792,91 beziehungsweise POKE 792,173. Natürlich können Spezialisten durch Verbiegen des Vektors auf andere Adressen ihre eigenen NMI-Routinen bauen.

Adresse 794 bis 795 ($31A bis $31B)

Vektor auf die OPEN-Routine des Betriebssystems

Die Routine beginnt ab Adresse 62282 ($F34A) - beim VC 20 ab 62474 ($FEAD). Diese Routine prüft, ob eine Datei (File) eröffnet werden kann. Das geht immer dann, wenn die File-Nummer nicht 0 ist und wenn weniger als 10 andere Dateien bereits eröffnet sind. Für die serielle Schnittstelle (Geräte-Nummer 4, 5, 8 bis 11) wird an das angewählte Gerät zuerst der Befehl »Listen« gegeben und dann die Sekundär-Adresse des OPEN-Befehls.

Beim Bandgerät (Geräte-Nummer 1) prüft die Routine den Tape Header einer sequentiellen Datei beziehungsweise schreibt einen Tape Header auf das Band.

Bei Anwahl der RS232-Schnittstelle (Geräte-Nummer 2) aktiviert die Routine einige Leitungen und reserviert je einen Ein- und Ausgabe-Pufferspeicher am oberen Ende des Basic-Programmspeichers.

Adresse 796 bis 797 ($31C bis $31D)

Vektor auf die CLOSE-Routine des Betriebssystems

Dieser Vektor zeigt auf die Adresse 62097 ($F291) — beim VC 20 auf 62282 ($F34A). Ab hier beginnt eine Routine, die beim CLOSE-Befehl zuerst prüft, ob die Datei-Nummer in der Tabelle der eröffneten Datei enthalten ist. Dann holt sie die dazugehörige Geräte-Nummer und Sekundär-Adresse und schließt den Kanal und die Datei.

Adresse 798 bis 799 ($31E bis $31F)

Vektor auf die CHKIN-Routine des Betriebssystems

Diese Routine beginnt ab Adresse 61966 ($F20E) — beim VC 20 ab 62151 ($F2C7). Sie eröffnet einen Datenkanal zur Übernahme von Daten von dem Gerät, das durch den OPEN-Befehl angegeben worden ist.

Adresse 800 bis 801 ($320 bis $321)

Vektor auf die CKOUT-Routine des Betriebssystems

Dieser Vektor zeigt auf die Adresse 62032 ($F250) — beim VC 20 auf 62217 ($F309). Dort beginnt die Routine, welche einen Datenkanal zur Abgabe von Daten an das im OPEN-Befehl angegebene Gerät aufmacht.

Adresse 802 bis 803 ($322 bis $323)

Vektor aufdie CLRCHN-Routine des Betriebssystems

Der Name dieser Routine ist die Abkürzung für »clear channel«. Diese Routine, die ab Adresse 62259 ($F333) — beim VC 20 ab 62451 ($F3F3) - beginnt, setzt alle Kanäle in den Einschaltzustand zurück. Das heißt, das Eingabegerät ist die Tastatur, das Ausgabegerät ist der Bildschirm.

Adresse 804 bis 805 ($324 bis $325)

Vektor auf die CHRIN-Routine des Betriebssystem

Dieser Vektor zeigt auf die Adresse 61783 ($F157) - beim VC 20 auf 61966 ($F20E). Die hier beginnende Routine, deren Abkürzung »Character Input« bedeutet, holt das jeweils nächste Byte vom Eingabepuffer des angewählten Gerätes, sofern ein solcher eingerichtet ist (zum Beispiel Kassettenpuffer, RS232-Puffer).

Bei Eingabe von der Tastatur holt diese Routine so lange Bytes aus dem Tastaturpuffer und zeigt sie auf dem Bildschirm an, bis das Zeichen für ein unge-SHIFTetes RETURN auftritt. Erst dann gibt die Routine das erste Zeichen der logischen Zeile auf dem Bildschirm an den Basic-Übersetzer weiter.

Adresse 806 bis 807 ($326 bis $327)

Vektor auf die CHROUT-Routine des Betriebssystems

Die CHROUT-Routine entspricht der CHRIN-Routine in der anderen Richtung. Sie bedeutet »Character Output« und transferiert ein Byte, das im Akkumulator steht, in den Puffer des angewählten Ausgabegerätes. Sie beginnt ab Adresse 62898 ($FlCA), - beim VC 20 ab 62074 ($F27A).

Adresse 808 bis 809 ($328 bis $329)

Vektor auf die STOP-Routine des Betriebssystems

Der Vektor zeigt auf die Adresse 63213 ($F6ED) - beim VC 20 auf 63344 ($F770). Die dort beginnende Routine prüft, ob die STOP-Taste gedrückt ist. Durch Verbiegen dieses Vektors kann die STOP-Taste abgeschaltet werden. Beim C 64 geht dies mit POKE 808,239; wieder eingeschaltet wird die STOP-Taste mit POKE 808,237. Beim VC 20 sind die Werte POKE 808,100 beziehungsweise POKE 808,112.

Adresse 810 bis 811 ($32A bis $32B)

Vektor auf die GETIN-Routine des Betriebssystems

Diese Routine ist fast identisch mit der CHRIN-Routine (siehe Speicherzellen 804 bis 805). Sie holt genauso Zeichen von angewählten Geräten in die Eingabepuffer. Der einzige und damit wichtigste Unterschied liegt in der Behandlung der Tastatur-Eingabe. Im Gegensatz zu CHRIN holt sie ein Byte aus dem Tastaturpuffer sofort in den Akkumulator. Der Vektor zeigt auf den Anfang der Routine ab Speicherzelle 61785 ($F13E) - beim VC 20 ab 61941 ($FlF5).

Adresse 812 bis 813 ($32C bis $32D)

Vektor auf die CLÄLL-Routine des Betriebssystems

CLALL ist die Abkürzung für Close All (Channels and Files). Diese Routine, die ab Adresse 62255 ($F32F) - beim VC 20 ab 62447 ($F3EF) — beginnt, setzt die Speicherzelle 152 auf 0 und schließt so zwangsläufig alle Dateien und Kanäle.

Adresse 814 bis 815 ($32E bis $32F)

Freier Vektor

Nach dem Einschalten zeigt dieser Vektor auf die BREAK-Routine, genauso wie der Vektor in Speicherzelle 790/791. Er ist ein Überbleibsel aus dem PET-Betriebssystem, das aber beim VC 20 und C 64 keine Rolle spielt. Hier können also eigene Vektoren definiert und eingesetzt werden.

Adresse 816 bis 817 ($330 bis $331)

Vektor auf die LOAD-Routine des Betriebssystems

Dieser Vektor zeigt auf die Adresse 62622 ($F49E) — beim VC 20 auf 62793 ($F549). Die dort beginnende Routine transferiert Daten von einem Eingabegerät direkt in den RAM-Speicher. Sie kann auch zum VERIFYen durch Vergleich der geLOADeten mit den ursprünglichen Daten verwendet werden.

Adresse 818 bis 819 ($332 bis $333)

Vektor auf die SAVE-Routine des Betriebssystems

Diese Routine ist das Gegenstück zur LOAD-Routine. Sie beginnt ab Adresse 62941 ($F5DD) - beim VC 20 ab 63109 ($F685).

Adresse 820 bis 827 ($334 bis $33B)

Freier Speicherbereich

Diese 8 Byte stehen zur freien Verfügung.

Adresse 828 bis 1019 ($33C bis $3FB)

Kassettenpuffer

Diese 192 Byte beherbergen den Kassettenpuffer. Der Name kennzeichnet diesen Speicherbereich als Zwischenspeicher für Ein- und Ausgabe-Operationen von und auf Band.

Dabei unterscheiden sich die normalen LOAD-, SAVE- und VERIFY-Befehle von den Datei-Befehlen INPUT#, GET# und PRINT#.

Bei LOAD, SAVE und VERIFY steht im Kassettenpuffer lediglich der Vorspann, der auf englisch »Tape Header« heißt. Die Funktion und Zusammensetzung des Tape Headers habe ich schon bei den Speicherzellen 183 bis 187 in Ausgabe 10/85, genau gesagt im Texteinschub »Tape Header« auf Seite 140 detailliert beschrieben. Die eigentlichen Daten berühren den Kassettenpuffer nicht, sondern werden direkt von und in den RAM-Speicher transferiert.

Eine Ergänzung zu der Erklärung des Tape Headers möchte ich noch nachtragen. Die Kennzahl im ersten Byte kann nicht nur, wie beschrieben, die Werte 1 und 3, sondern auch 2, 4 und 5 annehmen. Die Kennzahl 4 bezeichnet den Datenblock als Header einer Basic-Datei (GET# und so weiter), die Kennzahl 2 die danach folgenden Datenblöcke. Die Kennzahl 5 signalisiert, daß der Block das logische Ende des Bandes darstellt, und daß das Betriebssystem nicht weiter suchen muß.

Bei GET#, INPUT# und PRINT# werden nicht nur der Tape Header, sondern auch alle Daten im Kassettenpuffer zwischengespeichert. Dieser blockweise Transport ist an den charakteristischen Unterbrechungen des Datasettenmotors leicht zu erkennen.

Der Kassettenpuffer kann durch Verbiegen der Zeiger in Speicherzelle 178 bis 179 auf beliebige Plätze des Speichers, aber nicht unterhalb 512, geschoben werden. Normalerweise gibt das keinen Sinn, es sei denn, der Speicherbereich 828 bis 1019 wurde mit einem eigenen Maschinenprogramm belegt.

Adresse 1020 bis 1023 ($3K bis $3FF)

Freie Speicherplätze

Auch diese 4 Byte stehen zur freien Verfügung.

Liebe Leser, wir sind am Ziel unserer Wanderung durch die Speicherlandschaft des C 64 beziehungsweise des VC 20 angelangt. Ich muß zugeben, es hat länger gedauert, als ich mir zu Beginn vorgestellt habe. Schuld daran war nicht die Länge des Weges — die war durch Start bei Speicherzelle 0 und Ziel bei Speicherzelle 1023 fest vorgegeben. Aber ich habe gebummelt, ich habe viele »Wandervorschläge« gemacht und mir bei sehenswerten Adressen Zeit genommen, sie genauer zu besichtigen.

Ich will den Wandervergleich nicht weiter strapazieren, sondern mich zum Schluß bei allen Lesern, die mir Zuschriften, Fragen, Vorschläge und Verbesserungen geschickt haben, recht herzlich bedanken.

(Dr. H. Hauck/ah)

Texteinschub #1
Dem Computer ins Wort fallen

Jedesmal, wenn ein Computer eingeschaltet wird, würden seine vielen Schaltkreise und Speicherzellen irgendwelche ungeordneten Zahlen enthalten, wenn nicht ein bestimmter Schaltkreis ein RESET-Signal erzeugte. Dieses spezielle Signal geht an alle wichtigen Teile des Computers, nämlich an den Mikroprozessor und an die Bausteine für Ein- und Ausgabe.

Dadurch wird der Computer in einen definierten Anfangszustand versetzt, in dem entweder das Betriebssystem oder, falls vorhanden, ein selbststartendes Steckmodul die Befehlsgewalt erhält.

Die fest vorgegebenen Programmschritte dieser beiden lassen jedoch ein Arbeiten mit dem Computer ohne weiteres nicht zu. Wir könnten nämlich kein Resultat an ein Ausgabegerät (Drucker, Floppy, Datasette, Bildschirm) geben, und wir könnten auch keine Daten eingeben (Tastatur, Floppy, Datasette).

Der Computer wäre nicht steuerbar, wenn wir ihn nicht in seinem vorgegebenen Programmablauf unterbrechen könnten.

Die Unterbrechungsmöglichkeit heißt in der Fachsprache »INTERRUPT«.

Im Gegensatz zu den Großrechenanlagen, die meistens mit vielen Klassen von Interrupts ausgerüstet sind, haben die Heim-Computer von Commodore nur zwei Arten:

Ich habe nicht vor, Ihnen alle Details der Interrupt-Technik zu erklären. Das geht weit über den normalen Umfang meiner Texteinschübe hinaus. Sie können übrigens darüber in anderen Aufsätzen nachlesen, zum Beispiel von Helmut Welke in Ausgabe 11/84, Seite 84, oder im Assembler-Kurs von Heimo Ponnath in den Ausgaben 7 bis 9/85.

Aber einige Erklärungen, so hoffe ichjedenfalls, werden Ihnen auch hier das Interrupt-Prinzip deutlich machen.

Die beiden oben genannten Unterbrechungsarten unterscheiden sich sowohl dadurch, wer die Unterbrechung auslösen kann, als auch in der Art, wie sie gehandhabt werden.

NMI-Auslöser

sind Signale der RS232-Schnittstelle und der Autostart-Steckmodule. Dazu kommen noch die RESTORE-Taste, wenn sie gleichzeitig mit der RUN/STOP-Taste gedrückt wird, und der CIA # 2 beziehungsweise der VIA #1.

Wie gesagt, nähere Einzelheiten darüber finden Sie in den oben genannten Aufsätzen.

IRQ-Auslöser

ist 60mal in der Sekunde das Betriebssystem selbst, um die Werte von TI und TI$ höher zu setzen, um zu prüfen, ob die STOP-Taste gedrückt ist, um das Cursorblinken zu erzeugen, um die Tasten der Datasette und schließlich auch die Tastatur abzufragen. Ein IRQ-Interrupt kann aber auch durch Lesen oder Schreiben vom — beziehungsweise auf das — Band, durch die serielle Schnittstelle und durch die Rasterzeilen-Abtastung ausgelöst werden. Programmierbare IRQ-Interrupts sind möglich durch Sprite-Kollisionen, durch Lichtgriffel-Signale und durch den CIA # 1 beziehungsweise den VIA #2. Besonders durch die letzteren Ein-/ Ausgabe-Bausteine unterscheiden sich die Interrupts von C 64 und VC 20.

NMI-Abläufe

sind schon durch ihren Namen gekennzeichnet. »Non-Maskable« heißt soviel wie »nicht unterdrückbar«. Immer, wenn ein NMI-Signal ankommt, merkt sich der Computer, was er gerade macht, unterbindet alle IRQ-Signale und springt auf eine NMI-Routine, deren Beginn mit dem Vektor in Speicherzelle 792 bis 793 vorgegeben ist.

Herr Ponnath hat im Assembler-Kurs dies sehr treffend mit dem überkochenden Kessel auf dem Herd verglichen, der heruntergestellt werden muß, selbst wenn gerade die Türglocke klingelt, was uns normalerweise beim Lesen der Zeitung unterbrechen würde.

Erst in der NMI-Routine werden nach einer vorgegebenen Prioritätsliste alle NMI-Auslöser der Reihe nach abgefragt, bis der Verursacher gefunden ist.

IRQ-Abläufe

sind Maskable, das heißt sie können, wie gerade gesagt, unterdrückt werden, entweder durch programmiertes Abschalten — das entspricht dem Abstellen der Türglocke — oder durch ein NMI-Signal.

Bei einem IRQ-Signal wird zuerst der gerade laufende Befehl noch bearbeitet, dann startet die IRQ-Routine, deren Beginn durch den Vektor in Speicherzelle 788 bis 789 vorgegeben ist. In dieser Routine wird entschieden, ob der IRQ-Interrupt durch den Maschinencode-Befehl BRK (Break) oder duch angeschlossene Peripheriegeräte ausgelöst worden ist.

Wir sehen also, daß die Unterbrechungen einer festgelegten Priorität unterworfen sind. Ihre Steuerung aber erfolgt immer so, daß keine Interrupt-Anmeldung verloren geht, sondern jede in der gebührenden Reihenfolge abgearbeitet wird.

Schließlich sei noch hervorgehoben, daß der Sprung in die Interrupt-Routinen über die Vektoren die Möglichkeiten eröffnet, diese Routinen nach eigenem Geschmack abzuändern beziehungsweise durch eigene Routinen zu ersetzen.

PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →