Erschienen in 64'er Magazin, Ausgabe 12/1993 · Originaldatei: 12_93.TXT
Hinweis: Dies ist das an die Redaktion eingereichte Manuskript, nicht der gedruckte Endtext. Layout, Bildunterschriften, Korrekturen und Kürzungen der Redaktion können in der veröffentlichten Fassung abweichen.
Basic-Corner
Diesmal geht es um Befehle, die den Speicher des C 64 verwalten. Sie ermöglichen es, aus dem C 64 Dinge herauszuholen, die er eigentlich gar nicht kann. Beispielsweise sind jetzt nachträgliche Änderungen am Programm machbar, wir erringen die Kontrolle über die Elektronik des Computers, können Programme einfacher gestalten und noch komfortabler machen.
von Nikolaus M. Heusler
Bestimmt haben Sie sich schon einmal gefragt, wo der Computer eigentlich die Programme speichert, die Sie als Anwender eingeben. Wie kann er sich beliebige Zahlenwerte merken und jederzeit abrufbereit verwalten? Woher weiß er überhaupt, was er nach dem Einschalten genau zu tun hat, wie er auf welche Eingabe, welchen Befehl reagieren soll?
Sie wissen vielleicht, daß der C 64, wie jeder andere Computer auch, einen Speicher enthält, der alles aufnimmt, was Sie eingeben. Hier hinein wandern Ihre Basicprogramme, hier speichert der C 64 alle Eingaben. Ganz so einfach, wie das klingt, ist es zwar nicht. Aber nach der Lektüre dieser Folge und mit etwas Übung werden Sie nach kurzer Zeit keine Probleme mehr damit haben.
»Speicher« ist ein ziemlich abstrakter Begriff. Was haben wir uns darunter vorzustellen? Der Speicher (engl. »Memory«) könnte als »Notizpapier« des C 64 bezeichnet werden. Untersucht man ihn, stößt man auf genau 65536 verschiedene sogenannte »Speicherzellen«, die man sich tatsächlich wie Zellen in einem Gefängnis vorstellen kann. Sie sind von 0 bis 65535 durchnumeriert. Man nennt sie auch »Bytes«. Jede dieser Zellen kann genau einen von maximal 256 Zahlenwerten, die wiederum von 0 bis 255 durchnumeriert werden, aufnehmen. Die Zellen sind außerdem vollkommen unabhängig voneinander. Um wieder etwas deutlicher zu werden: Öffnen Sie eine der 65536 Zellentüren, so sitzt immer genau eine der 256 Zahlen in der Zelle. Später werden wir den Befehl, den es zu diesen Zweck tatsächlich gibt, genau kennenlernen.
Der C 64 ist wie eine lange Straße!
Steht ein Programm im Speicher des Computers, wird es auf mehrere dieser Zellen verteilt. Von den maximal 65536 vorhandenen stehen nicht alle für Basicprogramme zur Verfügung, sondern nur 38911, wie es auch im Einschaltbild steht.
Es gibt sieben Bereiche, in die der Speicher des C 64 aufgeteilt ist (Bild). Der erste erstreckt sich von Speicherzelle 0 bis einschließlich 2047 und wird »Zeropage« genannt. Der C 64 speichert hier wichtige Betriebsdaten, beispielsweise die Zeilennummer des Basicprogrammes, die er gerade abarbeitet, den Inhalt des sichtbaren Bildschirmes, die Länge des gespeicherten Basicprogrammes, welche Taste Sie drücken, Zwischenergebnisse von Rechnungen und vieles mehr. Unsachgemäße Manipulationen in diesem Bereich können unweigerlich zum Funktionsausfall führen. Er reagiert dann nur noch auf einen einzigen Tastendruck, den Ein/Ausschalter. Ihr Basicprogramm geht bei einem Absturz natürlich rettungslos verloren, wenn Sie es nicht vorher auf Diskette gespeichert haben.
Kleine graue Zellen
Der zweite Bereich steht dem Rechner zur Speicherung von Basicprogrammen und Variablen vollkommen zur Verfügung. Er umfaßt die erwähnten 38911 Bytes von 2048 bis 40959. Der Bereich von 40960 bis 49151 ist für uns weniger wichtig. Im »Basic ROM« ist hier von Commodore ein Programm fest gespeichert, das dem C 64 die Fähigkeit verleiht, Basicbefehle zu verstehen. Anders ist es da schon wieder mit dem Sektor, der sich von Zelle 49152 bis 53247 einschließlich erstreckt. Dieser Bereich wird von Basicprogrammierern weniger oft benutzt, vor allem Maschinenprogramme finden in diesen 4096 freien Bytes ihren Platz. In dem dreistöckigen Bereich von 53248 bis 57343 liegt im obersten Stockwerk, das normalerweise aktiv ist, der Ein- und Ausgabe-Sektor. Hier finden Sie die Bereiche zur Steuerung der Elektronik, die das Fernsehbild und den Ton des C 64 erzeugt, außerdem die sogenannten CIAs (Complex Interface Adapter), welche den Kontakt zur Außenwelt (Tastatur, Joystick, Diskettenstation, Drucker und so weiter) herstellen. Diese Bausteine sorgen dafür, daß Sie diese Geräte unter Basic mit unkomplizierten Befehlen ansprechen können. Ferner speichert der C 64 in seinem »Farb-RAM«, das von 55296 bis 56295 reicht, welche Farbe jedes Zeichen auf dem Bildschirm hat.
Im zweiten Stock findet sich wieder ROM-Gebiet, also Nur-Lese-Speicher. Hier ist das Aussehen der Buchstaben auf dem Bildschirm gespeichert. Man nennt diese Information »Zeichensatz«. Auch dieser Bereich wird von Commodore ab Werk fest programmiert. Als Basicprogrammierer haben Sie ohne besondere Tricks auf das Zeichensatz-ROM ebenso wenig Zugriffsmöglichkeit wie auf den RAM-Sektor, der »darunter« liegt. Schreib- oder Lesebefehle in diesem Bereich sprechen unter Basic stets den I/O-Speicher an. Der letzte Bereich von 57344 bis zur höchsten Speicherzelle 65535 enthält normalerweise das ROM, in dem das sogenannte »Kernal« oder »Betriebssystem« gespeichert ist. Dieses Programm sorgt dafür, daß der C 64 weiß, was er nach dem Einschalten zu tun hat, wie er auf Eingaben reagieren soll, und ähnliche Verwaltungsaufgaben.
Wie Sie vielleicht bemerkt haben, gibt es in jedem der Gebiete auch RAM-Speicher, der allerdings an manchen Stellen von anderen Bereichen (ROMs und I/O-Sektor) überdeckt wird und daher nicht ohne spezielle Programmierkenntnisse angesprochen werden kann. Die Regionen, die Sie problemlos als reinen RAM-Speicher benutzen, also sowohl lesen wie auch beschreiben können, sind im Bild durch dicke Umrandung markiert. Denken Sie daran, daß Manipulationen der Speicherzellen 0 bis 1023 (Zeropage) den Computer zum Absturz bringen können. Von 1024 bis 2047 findet sich der Bildschirmspeicher.
Lesen und Schreiben
Nun kommen wir zu den Befehlen, die Sie zum Lesen und Beschreiben des Speichers in Basic benutzen. Das erste Kommando ist eigentlich kein Befehl, sondern eine Funktion, die innerhalb von mathematischen Berechnungen eingesetzt werden kann. Sie lautet
PEEK (X)
und liefert als Ergebnis den Inhalt der Speicherzelle X. Für X sind Werte von 0 bis 65535 erlaubt. Die Eingabe
PRINT PEEK (214)
liefert etwa den Inhalt der Speicherzelle 214. Diese Zelle, sie befindet sich in der Zeropage, enthält die Zeile, in der sich der Cursor momentan befindet. Obiger Befehl gibt also die aktuelle Zeilennummer auf dem Bildschirm aus. Wenn Sie eingeben:
A = PEEK (2) + 1
so wird der Variablen A der um eins erhöhte Inhalt der (übrigens unbenutzten) Speicherzelle zwei zugewiesen. Enthält diese Zelle den Wert Null, wie es nach dem Einschalten der Fall ist, bekommt A den Wert 0+1 = 1. Sie sehen: Die PEEK-Funktion kann als normale Operation in Berechnungen verwendet werden. Also auch bei IF:
20 IF PEEK(198) = 0 THEN 20
Diese Zeile bedeutet: Solange die Speicherzelle 198 (sie enthält die Anzahl der gedrückten Tasten) den Wert Null (keine Taste gedrückt) hat, gehe zurück zu Zeile 20. Diese Zeile hält das Programm also so lange auf, bis eine Taste gedrückt wird. Der Nutzen liegt auf der Hand: Nehmen wir einmal an, in einem Programm soll die Meldung ausgegeben
BITTE DRUCKER ANSCHALTEN UND TASTE DRÜCKEN!
und danach auf eine Taste gewartet werden. Dazu geben wir erst den Text mit PRINT aus und verwenden dann obige Befehlsfolge:
10 PRINT "BITTE DRUCKER ANSCHALTEN!" 15 PRINT "BITTE TASTE DRÜCKEN!" 20 IF PEEK (198) = 0 THEN 20
Ein anderes Beispiel: Lesen Sie eine Speicherzelle, deren Inhalt vom C 64 periodisch mit extrem hoher Geschwindigkeit geändert wird, so läßt sich die PEEK-Funktion auch zur Erzeugung von Zufallszahlen einsetzen, da der Inhalt der Zelle zum Zeitpunkt des Auslesens nicht abzusehen ist. Eine solche Speicherzelle ist 53266. Sie enthält die Nummer der Zeile auf dem Bildschirm, die der Videochip gerade an den Fernseher ausgibt. Der Videochip ist ja dafür verantwortlich, daß Sie irgend etwas auf Ihrem Monitor oder Fernseher zu Gesicht bekommen. Da 25 mal in der Sekunde ein neues Bild mit etwa 300 solcher Zeilen erzeugt wird, ändert sich der Inhalt dieser Speicherzelle etwa 15000 mal in der Sekunde. So schnell, daß man ein System in der Änderung erkennen würde, kann man diese Zelle in Basic gar nicht abfragen! Geben Sie einmal ein:
FOR I = 1 TO 10000 : PRINT PEEK (53266) : NEXT
Diese Befehlsfolge liest zehntausend Mal hintereinander den Inhalt der Speicherzelle 53266 aus und gibt ihn auf dem Bildschirm aus. Nach dem Druck auf die RETURN-Taste erscheint eine Reihe von Zahlen. Anhand dieser Liste können Sie erkennen, wie schnell und scheinbar chaotisch sich der Inhalt dieser Zelle ändert. Wenn Sie sich sattgesehen haben, drücken Sie die Taste RUN STOP.
Interessiert Sie, wie man feststellen kann, welche Programmzeile des Basicprogrammes gerade bearbeitet wird? Die beiden Speicherzellen 57 und 58 enthalten zusammen in verschlüsselter Form die Nummer der Basic-Zeile, die der Basic-Interpreter gerade abarbeitet. Innerhalb eines Basicprogrammes kann dieser Wert durch
PRINT PEEK (57) + 256 * PEEK (58)
ermittelt werden. Schreiben Sie diesen Befehl in einem Basicprogramm etwa in Zeile 456:
456 PRINT PEEK (57) + 256 * PEEK (58)
so gibt der Computer nach dem Start mit RUN an dieser Stelle die Zahl 456, also die Nummer der Zeile, in der der Befehl steht, aus. Auch diese beiden Speicherzellen liegen in der Zeropage, daran können Sie ersehen, wie wichtig für den C 64 dieser Bereich ist. Wenn Sie sich für den genauen Aufbau der Zeropage interessieren, sehen Sie sich einmal die letzten Seiten des Handbuches an (»Speicherbelegung«). Hier wird die Funktion fast jeder Zelle erklärt.
Nun wollen wir aber Speicherzellen nicht nur lesen, sondern ihnen auch einen neuen Inhalt geben, sie also beschreiben. Der Umkehrbefehl zu PEEK lautet:
POKE Zellennummer, neuer Inhalt
Er weist der angegebenen Zelle den neuen Inhalt zu. Als Zellennummer sind wieder Zahlen oder numerische Ausdrücke von 0 bis 65535 erlaubt, der Inhalt darf bekanntlich von 0 bis 255 gehen. Im Gegensatz zu Zahlen sind numerische Ausdrücke auch Berechnungen, auch in Kombination mit Variablen. Der Befehl
POKE 2,123
schreibt den Wert 123 in die sonst unbenutzte Speicherzelle 2. Geben Sie jetzt
PRINT PEEK (2)
ein, um den Inhalt dieser Zelle auf dem Schirm anzuzeigen, so bekommen Sie als Anwort den neuen Wert zurück: 123. Tip: Geben Sie jetzt ein kurzes Basicprogramm ein und starten es mit RUN. Nach dem Ablauf lesen Sie wiederum den Inhalt der Zelle 2: Immer noch 123. Im Gegensatz zu reinen Basicvariablen löscht der C 64 bei RUN, NEW oder CLR nicht den Inhalt des Speichers. So lassen sich Werte zwischen mehreren Basicprogrammen übermitteln, oder nach dem Ende beim nächsten Lauf eines Programms weiterverwenden. Erst beim Abschalten des Computers werden die Zellen gelöscht.
Gezielte Manipulationen
Wir wollen den neuen Befehl nun anhand von konkreten Beispielen kennenlernen. Die Speicherzelle 53280 enthält die Nummer der Farbe, die der Rahmen, der um den Bildschirm gelegt wird, momentan hat. Sie kann durch
POKE 53280, X
(X ist die neue Farbnummer nach der Tabelle im Handbuch) also neu eingestellt werden. Gefällt Ihnen die Farbe nicht, können Sie sie durch
POKE 53280, 1
beispielsweise auf »weiß« stellen.
Sie haben vorhin gelernt, daß es auch Bereiche gibt, deren Inhalt Sie nicht verändern können (die »ROM-Bereiche«). Ein solcher Bereich geht etwa von 57344 bis 65535. Doch was passiert, wenn wir versuchen, eine solche Speicherzelle mit POKE zu beschreiben? Probieren wir es aus, beispielsweise anhand der Speicherzelle 57344. Schalten Sie den Computer aus und wieder ein. Jetzt lesen wir den Inhalt dieser Speicherzelle zur Kontrolle einmal aus:
PRINT PEEK (57344)
Die Zahl 133 erscheint, denn das wurde dem Computer ja ab Werk so mitgegeben. Nun hätten wir gerne den Wert 0 in dieser Speicherzelle:
POKE 57344,0
Welcher Wert befindet sich nach diesem Befehl in der Speicherzelle? Die 0, weil wir das mit dem POKE-Befehl so definiert haben, oder die 133, weil der Inhalt dieser Zelle nicht variabel ist? Probieren wir es aus:
PRINT PEEK (57344)
schafft Klarheit: Der Inhalt hat sich nicht verändert, es steht immer noch die 133 darin.
Etwas anderes: Wie bereits mehrfach erwähnt, sichert der C 64 in der Zeropage wichtige Betriebsdaten. Daher können ungewollte Manipulationen zum Absturz führen. Durch gezieltes Verändern von Zellen können aber durchaus nützliche Effekte erreicht werden. So bewirkt etwa
POKE 774, 226: POKE 775, 252
daß der Versuch, ein Programm zu listen, mit einem Reset bestraft wird. Ein Reset (engl. für Zurückstellen, in den Ausgangszustand bringen) ist die Prozedur, die beim Ein- und Ausschalten des Computers durchgeführt wird, um den C 64 auf die Arbeit vorzubereiten. Dabei werden alle Programme gelöscht, die Bildschirmfarben gesetzt, die Einschaltmeldung ausgegeben, die Tastatur eingeschaltet und so weiter. Probieren Sie's aus: Geben Sie die beiden POKE-Befehle ein, erzeugen Sie dann ein kurzes Basicprogramm, zum Beispiel
10 PRINT "DIES IST EIN TEST" 20 END
Danach probieren Sie einmal das Kommando
LIST
aus: Anstatt das Programm im Speicher auf dem Bildschirm zu präsentieren, tut der C 64 für wenige Sekunden einmal gar nichts, dann erscheint plötzlich das Einschaltbild: Als ob Sie den Computer aus- und wieder eingeschaltet hätten. Den Normalzustand erreichen Sie durch
POKE 774, 26: POKE 775, 167
Ein anderes Beispiel: Der Befehl
POKE 650, 128
schaltet die Dauerwiederholungsfunktion (sonst nur etwa bei den Cursortasten oder SPACE) auf alle Tasten des C 64. Wenn Sie nach der Eingabe dieses Befehles lange Zeit eine Buchstabentaste drücken, beginnt der C 64 nach kurzer Zeit, laufend neue Buchstaben dieses Typs auszugeben.
Auch zur Sicherung von Programmen lassen sich solche Spielereien verwenden: Durch Eingabe von
POKE 808, 251
wird es unmöglich gemacht, ein Programm zu stoppen. Außerdem liefert der LIST-Befehl unsinnige Zeilennummern. Hier lautet der Normalzustand
POKE 808, 237
Sehr wichtig ist die Speicherzelle 198, die die Anzahl der Tasten angibt, die sich der C 64 gemerkt hat. Wie Sie vielleicht schon wissen, reagiert der Computer auch auf Tastendrücke, während der Cursor gar nicht blinkt, weil ein Programm läuft. Wenn der C 64 fertig ist, werden die Tasten dann ausgeführt. Manchmal kann das aber äußerst störend sein, beispielsweise in einem Menü. Hier sollte der C 64 alle während der Ausführung des letzten Menüpunktes gedrückten Tasten vergessen und erst danach wieder auf Tasten reagieren. Kein Problem,
POKE 198,0
erledigt das »Vergessen« für uns. Ein Anwendungsbeispiel findet sich sogar in diesem Artikel. Weiter oben haben Sie ein kurzes Programm kennengelernt, das aufforderte, den Drucker einzuschalten und dann eine Taste zu drücken. Vor dem Test, ob eine Taste gedrückt wurde, sollte man den Befehl
18 POKE 198,0
einbauen. Er stellt vor der Abfrage sicher, daß wirklich nur auf Tasten reagiert wird, die nach Zeile 18 gedrückt wurden.
Ein weiterer Befehl, der uns hier mehr am Rande interessieren soll, ist der SYS-Befehl. Falls Sie schon etwas Erfahrung mit Maschinensprache haben, wissen Sie, daß jedes Maschinenprogramm an einer definierten Stelle im Speicher stehen muß. Zum Start des Maschinenprogrammes verwenden Sie nun den SYS-Befehl:
SYS Adresse
Aber auch der Nur-Basic-Programmeierer profitiert vom SYS-Befehl. Der C 64 hat nämlich eine große Menge von Maschinenprogrammen bereits fest eingebaut, die gewöhnlich zur Steuerung des Computers dienen. Teilweise erfüllen diese Programme (sie sind im ROM gespeichert, gehen also beim Ausschalten nicht verloren) recht sinnvolle Funktionen:
SYS 58692
beispielsweise löscht den Bildschirm, und
SYS 64738
der wohl am meisten gebrauchte SYS-Befehl, löst die sogenannte »Reset-Routine« aus, die intern (fast) so wirkt, als ob der C 64 ein- und wieder ausgeschaltet wird. Sie haben diesen Effekt ja schon vorhin bei unserer kleinen LIST-Beeinflussung kennengelernt, als nach Eingabe von
LIST
ein Reset ausgelöst wurde. Bei professionellen Programmen steht der Befehl
SYS 64738
am Ende, damit niemand Gelegenheit hat, sich das Programm nach dem Ablauf anzusehen. Bei Reset wird das Programm ja aus dem Speicher gelöscht.
Wie gesagt, der SYS-Befehl soll hier nur am Rande besprochen werden. Für Basic-Programmierer ohne Assembler-Ambitionen spielt er auch nur eine untergeordnete Rolle. Durch die Befehle PEEK und POKE jedoch können Sie eigene Programme schon viel professioneller und komfortabler gestalten. Unten finden Sie Beispiele für die sinnvolle Anwendung der Kommandos PEEK, POKE und SYS. Wenn Sie ein wenig damit experimentieren, erlangen Sie sicherlich sehr bald das für den optimalen Einsatz der neuen Befehle notwendige Fingerspitzengefühl.
Wir wünschen Ihnen viel Vergnügen bei Ihrem unermüdlichen Experimentieren mit den Speicherbefehlen. Für Rückfragen und Vorschläge finden Sie bei uns immer ein offenes Ohr. (hb)
Bild
Wir können uns den Speicher des C 64 wie eine lange Straße vorstellen. Einige Bereiche sind mehrfach belegt.