POKE und PEEK
POKE (englisch to poke = stecken, stoßen) ist eine Anweisung der Programmiersprache BASIC, die dazu dient, einen als Zahl angegebenen Wert (bei 8-Bit-Architekturen ein Oktett bzw. Byte) in die angegebene Speicheradresse im Adressraum des Prozessors (der CPU) zu speichern.[1] Sein Gegenpart ist die PEEK-Interpreterfunktion (englisch to peek = gucken, spähen, nachsehen), mit der von einer Adresse gelesen wird; der gelesene Wert wird dem BASIC-Programm als Rückgabewert übergeben.[2]
Mit der POKE-Anweisung kann beispielsweise der Inhalt einer Speicherzelle des Arbeitsspeichers des Rechners manipuliert werden. Daneben werden mit POKE und PEEK die Hardwaresteuerregister von Peripheriebausteinen des Computers für das BASIC-Programm zugänglich, sofern das Computersystem mit Memory Mapped I/O arbeitet.
Die Befehle PEEK und POKE wurden von Bill Gates und Paul Allen 1975 in der Programmiersprache Altair BASIC eingeführt.[3]
Funktion
Der POKE-Befehl ruft eine Routine des BASIC-Interpreters auf, die einen Schreibzugriff mit den beiden Parametern für Adresse und Wert durchführt. Die PEEK-Funktion wertet ihren Parameter als Adresse aus, führt einen Lesezugriff auf ebendiese Adresse aus und übergibt das Resultat als Rückgabewert an das BASIC-Programm.
- Format
POKE Adresse, Wert
Wert = PEEK(Adresse)
Der maximale Wert der Adresse ist abhängig von der Breite des Adressbusses. Der maximale Wert ist abhängig von der Breite des Datenbusses. Bei 8-Bit-Architekturen sind typische Werte 0 bis 65535 für eine 16-Bit-Adresse und 0 bis 255 für einen 8-Bit-Wert. Sollte das zugrundeliegende Computersystem in seiner Speicherbelegung Lücken aufweisen und auch keine Adressierungsfehler-Ausnahmebehandlung implementiert sein, so bewirkt eine POKE-Anweisung auf eine unbelegte Adresse nichts, während die entsprechende PEEK-Funktion einen undefinierten Rückgabewert liefert.
Verwendung
In der Ära der Heimcomputer wurde der POKE-Befehl oft verwendet, da dies für BASIC-Programme auf vielen Systemen die einzige Möglichkeit ist, bestimmte Grafik- oder Sound-Fähigkeiten des Rechners zu nutzen, die zwar von der benutzten Hardware, nicht aber durch im BASIC-Interpreter eingebaute Befehle unterstützt werden. Das BASIC-Programm erhält so Zugriff auf die Hardwaresteuerregister und steuert damit die Hardware direkt; eine Aufgabe, die nach zeitgenössischer Terminologie einem Gerätetreiber zufallen würde.
- Beispiel
POKE 53265, PEEK(53265) OR 32
- Setzt durch Lesen mittels PEEK, Modifizieren mittels OR 32 und Zurückschreiben mittels POKE Bit 5 (das mit der Wertigkeit 25 = 32) im Register 17 des Peripheriebausteins VIC II (des Video Display Controllers) in einem Commodore 64; dort hat der VIC II (durch Memory Mapped I/O) die Basisadresse D00016 = 53248, Register 17 liegt demnach an Adresse 53248 + 17 = 53265. Das gesetzte Bit 5 dieses Registers bewirkt, dass der Bitmap-Grafikmodus aktiviert wird.[4] Die Verknüpfung mit OR bewirkt, dass alle gelesenen Bits unverändert zurückgeschrieben werden – bis auf das Bit 5, das zustandsunabhängig gesetzt wird. Analog hierzu kann Bit 5 mit
POKE 53265, NOT(PEEK(53265)) NOR 32
oderPOKE 53265, PEEK(53265) AND NOT(32)
zustandsunabhängig gelöscht und mitPOKE 53265, NOT(PEEK(53265)) XNOR 32
oderPOKE 53265, PEEK(53265) XAND NOT(32)
zustandsabhängig umgeschaltet (toggle) werden.
- Setzt durch Lesen mittels PEEK, Modifizieren mittels OR 32 und Zurückschreiben mittels POKE Bit 5 (das mit der Wertigkeit 25 = 32) im Register 17 des Peripheriebausteins VIC II (des Video Display Controllers) in einem Commodore 64; dort hat der VIC II (durch Memory Mapped I/O) die Basisadresse D00016 = 53248, Register 17 liegt demnach an Adresse 53248 + 17 = 53265. Das gesetzte Bit 5 dieses Registers bewirkt, dass der Bitmap-Grafikmodus aktiviert wird.[4] Die Verknüpfung mit OR bewirkt, dass alle gelesenen Bits unverändert zurückgeschrieben werden – bis auf das Bit 5, das zustandsunabhängig gesetzt wird. Analog hierzu kann Bit 5 mit
Mit POKE-Anweisungen können gezielt bestimmte Daten des Betriebssystems geändert werden, um vom Anwender gewünschte Effekte zu erzielen – beispielsweise Ändern der Tastenwiederholung. Ein anderes Beispiel aus dieser Kategorie für die PEEK-Funktion ist, das bloße Drücken der Shift-Taste (ohne weitere Taste) zu erkennen, wenn das Betriebssystem dafür anderweitig keine Möglichkeit bietet.
- Beispiel
POKE 650, 128
- Tastenwiederholung für alle Tasten eines Commodore 64 aktivieren. An Adresse 650 (eine normale Hauptspeicheradresse im Bereich der Betriebssystem-Verwaltungsdaten) schaut der Tastaturabfrage-Teil des Betriebssystems nach, wie die Tastenwiederholung arbeiten soll. Der Wert 128 bewirkt, dass alle Tasten wiederholt werden; Alternativen sind keine Taste wird wiederholt sowie nur Cursor- und Löschtasten und Leerschlag werden wiederholt.
- Beispiel
IF PEEK(653) AND 1 THEN …
- Abfrage des Shift-Indikator-Bits (Bit 0 (mit der Wertigkeit 20 = 1) des Bytes an Adresse 653) der Betriebssystem-Tastaturabfrage eines Commodore 64.[5] Der Teil hinter THEN wird nur ausgeführt, wenn die Shift-Taste gerade gedrückt ist.
Eine weitere Anwendung ist ein BASIC-Programm, das für seine Aufgabe eine in Maschinensprache erstellte Unterroutine benutzt. Statt diese Unterroutine (mitunter nur wenige Bytes) als eigene Binärdatei vom Massenspeicher (in der Heimcomputer-Ära oft einfache Kassettenrekorder bzw. Datasetten) zu laden, wird das Speicherabbild der Unterroutine als Zahlenfolge im BASIC-Programm abgelegt. Während der Initialisierungsphase schreibt das BASIC-Programm dieses Speicherabbild in einer Schleife mittels POKE-Anweisungen an die gewünschten Ziel-Speicheradressen, so dass die Unterroutine anschließend dort aufgerufen werden kann. Bekannt ist auch das Patchen (Modifizieren) von Maschinenspracheprogrammen durch gezielte POKE-Anweisungen nach dem Laden vom Massenspeicher und vor Programmstart – insbesondere zum Cheaten von Computerspielen. In der einschlägigen Szene sind beispielsweise Cheats bekannt, mit denen die Spielerfigur unverwundbar ist oder ihr zumindest deutlich mehr „Leben“ zur Verfügung stehen. Die Kombination von Wert und Adresse ist für jedes Programm bzw. Spiel individuell (ermittelt beispielsweise mit Methoden des Reverse Engineerings) und wird bisweilen selbst als POKE bezeichnet (z. B. „POKE-Liste“ im Sinne von Auflistung von Cheats).
Um als Programmierer zu wissen, welche Kombinationen von Adressen und Werten einen gewünschten Zweck erfüllen, hilft das Studium von Dokumentation (Bedienungsanleitungen und Datenblättern) sowie weiterer Literatur (auch Artikel in Fachzeitschriften) zu den Peripheriebausteinen, zum Betriebssystem etc.
Die Benutzung von POKE-Anweisungen vermindert vielfach die Lesbarkeit und Nachvollziehbarkeit des Programm-Textes; zugleich ist sie die Ursache dafür, dass entsprechende Programme kaum portabel zwischen verschiedenen Computermodellen und deren unterschiedlichen Chipsätzen sind – auch zwischen verschiedenen Modellen oder Baureihen des gleichen Herstellers sind POKE-Befehle oft nicht übertragbar. Die Beispiele oben zur Tastatursteuerung für den Commodore 64 lassen sich auf den Commodore VC 20 übertragen, da sich die Betriebssysteme diesbezüglich sehr ähneln. Die Video Display Controller beider Rechner unterscheiden sich allerdings nicht nur in ihrer Position im Speicherbelegungsplan, sondern auch im inneren Aufbau – hier: es gibt beim VC 20 keinen Bitmap-Grafikmodus –, sodass das Beispiel für das Aktivieren des Bitmap-Grafikmodus beim VC 20 keine Entsprechung hat.
Da mit dem POKE-Befehl auch Verwaltungsdaten des Betriebssystems überschrieben werden können, kommt es bei unbedachtem Einsatz oft nicht zu einer ordentlichen Fehlermeldung, sondern zu einem Computerabsturz – mit potentieller Zerstörung des Programms oder der Daten im Speicher. Auch können unerwünschte optische oder akustische Effekte auftreten, wenn Fehler bei der Programmierung der Hardwaresteuerregister auftreten. Im besten Falle geschieht einfach nichts. Die Fehlersuche ist durch die erwähnten Effekte erheblich erschwert.
Heutige Bedeutung
Auf heutigen Systemen und unter Verwendung aktueller BASIC-Varianten ist die Verwendung von POKE obsolet. Heutige CPUs verwenden zu Adressbildung ausschließlich die MMU, welche die logische Adresse von der physikalischen abstrahiert und durch spezielle Schutzmechanismen die direkte Speichermanipulation unterbindet (Speicherschutzverletzung). Hinzu kommt, dass moderne Betriebssysteme mit wenigen Ausnahmen nicht mehr über einen statischen Speicherbelegungsplan verfügen, bei dem bestimmte Inhalte stets an denselben Adressen vorgefunden werden könnten. Der Zugriff auf Hardware-Ressourcen erfolgt dann nicht über fixe Adressen, sondern über Gerätetreiber, welche wiederum dafür vorgesehene Speicherbereiche auslesen und beschreiben.
Einzelnachweise
- POKE. In: Microsoft QuickBasic 4.5 Advisor. Microsoft, 1990, abgerufen am 27. Februar 2014 (englisch).
- PEEK. In: Microsoft QuickBasic 4.5 Advisor. Microsoft, 1990, abgerufen am 27. Februar 2014 (englisch).
- N.Montfort, P.Baudoin, J.Bell, I.Bogot, J.Douglass u. a. 10PRINT CHR$(205.5+RND(1)); : GOTO 10 Cambridge, MIT Press (2013) ISBN 978-0-262-01846-3 S. 171 (Online. (PDF 50 MB) Abgerufen am 26. Februar 2014 (englisch).)
- POKE. In: C64 Wiki. Abgerufen am 14. April 2015.
- Commodore 64 memory map. Abgerufen am 16. April 2015.