MEGAMON - Speichermonitor für Assemblerfreaks - ----------------------------------------
Wer Assembler programmiert kennt sie: die Speichermonitore, mit denen man schnell mal was assemblieren oder disas- semblieren, oder kurz einen Blick in den Speicher wagen kann. Ein jeder Maschi- nensprache-Coder kommt nicht um ein solch nützliches Programm herum, das viele Funktionen zur Unterstützung der täglichen Programmier-Arbeit bereit- stellt. Auch wir von der MagicDisk wol- len Ihnen nun ein solches Programm vor- stellen: den "MegaMon". 1) ALLGEMEINE BEDIENUNGSHINWEISE Wie schon erwähnt ist der MegaMon ein mächtiges Hilfsprogramm, das vor allem die Assemblerprogrammierer unter Ihnen unterstützen soll. Daher ist es auch erforderlich, wenigstens einige Grund- kenntnisse über die Maschinensprache des 6510-Prozessors (so wie er im C64 Ver- wendung findet) zu verfügen, um die Funktionsweise des Programms zu verste- hen. Da dies hier eine Programmanleitung ist, und kein Assembler-Kurs, muß ich Sie diesbezüglich leider auf entspre- chende Literatur verweisen. Die Anlei- tung geht davon aus, daß Sie sich mit den Assembler-Befehlen, sowie Speiche- raufteilung und IRQs des C64 auskennen. a) DER ERSTE PROGRAMMSTART Der Mega-Mon ist ein reines Assembler- Programm, das sich im Speicherbereich von $8000-$A000 (dez. 32768-40960) breit macht. Da dies nicht die BASIC- Startadresse ist, versteht es sich daß Sie ihn absolut, also mit der Endung ",8,1" in den Speicher laden müssen. Gestartet wird das Programm dann mit einem "SYS32768", woraufhin auch gleich schon eine Programminformation, sowie die Registeranzeige auf dem Bildschirm erscheint. Beim Initialisieren richtet sich der MegaMon übrigens einen BRK-, sowie einen NMI-Interrupt ein, die beide den MegaMon starten, sobald sie auftre- ten. BRK-Interrupts sind softwaremässige Unterbrechungen, die der Prozessor selbst erzeugt, sobald er auf den Assem- bler-Befehl "BRK" (Opcode $00) stößt. Der NMI-Interrupt kann als Timer- Unterbrechung von CIA2 ausgelöst werden, wo er im Betriebssystem des C64 jedoch keine Verwendung findet. Allerdings ist die 'RESTORE'-Taste direkt mit dem NMI- Eingang des Prozessors verbunden, womit Sie sie dazu benutzen können, den Mega- Mon direkt per Tastendruck zu starten. Dies funktioniert natürlich nur, wenn er mindestens einmal mit dem obig genannten SYS-Befehl gestartet wurde, um den NMI zu initialisieren, und auch nur solange wie der NMI-Vektor unverändert bleibt. Letzterer wird nämlich beim Auslösen eines RESETs wieder zurückgesetzt, so daß Sie den MegaMon ebenfalls wieder per SYS starten müssen. b) DIE REGISTERANZEIGE Sie erscheint immer nachdem der MegaMon aufgerufen wurde, sowie nach Benutzen des "R"-Befehls des Monitors. Sie zeigt Ihnen den Status des Prozessors, zum Zeitpunkt des Aufrufs, an. Dies ist ins- bersondere nützlich, wenn Sie das Pro- gramm zum Austesten eigener Programme benutzen möchten. Nachdem der MegaMon initialisiert wurde, können Sie in Ihrem eingenen Programm einen BRK-Befehl ein- setzen und selbiges starten. Erreicht der Prozessor nun den BRK-Befehl, so springt er sofort in den MegaMon, der Ihnen den Status des Prozessors und sei- ner Register anzeigt, womit Sie prüfen können, welche Werte Ihr Programm gerade am Bearbeiten war, und in welchem Zu- stand es sich befand. Die einzelnen Wer- te der Tabelle haben folgende Bedeutung: PC: Dies ist der "Program-Counter", der anzeigt, an welcher Speicheradresse das Programm unterbrochen wurde. SR: Dies ist das Status-Register des Prozessors, in dem die Prozessor- Flags untergebracht sind. An ihm können Sie (durch Umrechnung in Binärschreibweise) ablesen, ob z.B. das Carry- oder Zero-Bit zum Zeit- punkt der Unterbrechung gesetzt war. AC: Der Inhalt des Akkus, zum Zeitpunkt der Unterbrechung. XR: Der Inhalt des X-Registers. YR: Der Inhalt des Y-Registers. SP: Der Zustand des "Stack-Pointers", der vermerkt wieviele Bytes momentan auf dem Stapel liegen. c) BEFEHLE UND KONVENTIONEN Alle Zahlenangaben werden im gesamten Programm in hexadezimaler Schreibweise ausgegeben, und müssen auch von Ihnen in dieser Form angegeben werden. Die einzelnen Funktionen des Programms werden über einfache Befehle aufgerufen, die Sie hinter einer Eingabeaufforderung (repräsentiert durch einen Punkt) einge- ben müssen. Alle Befehle werden durch einen einzelnen Buchstaben ausgedrückt, dem je nach Funktion einer oder mehrere Parameter nachgestellt sein können. Sel- bige werden IMMER mit Kommata voneinan- der getrennt. Desweiteren muß dem Be- fehlsbuchstaben immer ein Punkt vorans- tehen, damit er erkannt wird. Da Sie im MegaMon genauso über den Bildschirm fah- ren können, wie im normalen Basic-Editor des C64, können Sie so auch jede belie- bige Zeile zur Eingabe eines Befehls nutzen. Eine jede Befehls-Zeile muß durch Drücken der 'RETURN'-Taste bestä- tigt werden, was zur eigentlichen Ausführung des Befehls führt. Weiterhin besteht bei Befehlen, die Ih- nen irgendwelche Speicher-, Register- oder diassemblierte Programminhalte auf dem Bildschirm anzeigen die Möglichkeit, mit dem Cursor in eine Zeile zuvor zu fahren und eine Änderung der Daten dort in der Anzeige einzutragen. Drücken Sie dann die 'RETURN'-Taste, so wird die entsprechende Zeile untersucht, und die dort eingetragenen Änderungen in den Speicher übertragen. Dadurch können Sie sich Speicherbereiche nicht nur ansehen, sondern auch modifizieren. Bei solchen Befehlen kann es auch sein, daß der Me- gaMon mehr auszugeben hat, als auf dem Bildschirm darstellbar ist. In diesen Fällen gilt immer, daß Sie die Ausgabe durch Drücken der 'SPACE'-Taste anhalten und auch wieder fortsetzen können; mit 'RUN/STOP' brechen Sie sie ganz ab. 2) DIE STANDARD-FUNKTIONEN DES MEGAMON Kommen wir nun zur Beschreibung der Grundfunktionen des Programms. Wie schon erwähnt werden Sie durch einen Buchsta- ben repräsentiert, der je nach Befehl von einem oder mehreren Parametern ge- folgt sein kann: a) "A" - ASSEMBLE Diese Funktion ist ein einfacher Folgen- Assembler. Sie geben nacheinander die gewünschten Maschinensprache-Befehle in ihrer Textform ein, die vom MegaMon so- gleich übersetzt werden und als Assem- bler-Opcodes in den Speicher geschrieben werden. Hierzu müssen Sie dem "A" eine Adresse nachstellen, an die assembliert, sowie den Assembler-Befehl, der an die- ser Adresse untergebracht werden soll (z.B. ".A 1000 LDY#$00"). Nachdem dieser nun eingetragen ist, errechnet der Mega- Mon automatisch die nächste Adresse und gibt Ihnen die Möglichkeit, weitere Be- fehle (ohne "A"+Adresse) einzugeben. Versteht er einen Ihrer Befehle nicht, so bricht er den Assemble-Modus ab, und gibt ein Fragezeichen hinter der besag- ten Zeile aus. Korrigieren Sie diese Zeile nun, so wird in der Assemblierung fortgefahren. Möchten Sie sie abbrechen, so geben Sie gar nichts ein, und drücken einfach nur 'RETURN' um wieder in den Kommando-Modus zurückzukehren. Achten Sie bitte darauf, daß diese Funktion bei Angabe von Sprungadressen, sowie Zahl- werten IMMER hexazedimale Zahlen ver- langt, denen Sie ein "$"-Zeichen voran- setzen müssen. Ohne dieses Zeichen ver- weigert der MegaMon die Annahme des ent- sprechenden Befehls. b) "B" - BASIC Dieser Befehl verlangt keine Parameter und löst lediglich einen RESET aus. c) "C" - COMPARE Mit dieser Funktion können Sie den In- halt zweier Speicherbereiche miteinander vergleichen. Geben Sie hierzu die Start- und Endadresse des ersten Bereichs, so- wie die Startadresse des zweiten Be- reichs an, jeweils durch Kommata vonei- nander getrennt (z.B. ".C 2000,20FF,3000 - vergleicht den Inhalt des Speicherbe- reichs von $2000 bis $20FF mit dem In- halt ab $3000). Der MegaMon vergleicht nun jedes einzelne Byte des ersten Be- reichs, mit dem entsprechenden Byte des zweiten Bereichs und gibt Ihnen bei Nicht-Öbereinstimmung die Adresse aus, an der sich zwei Bytes voneinander un- terscheiden. Dies tut er für alle Bytes des angegebenen Bereichs, bevor er wie- der in den Kommandozeilen-Modus zurück- kehrt. d) "D" - DISASSEMBLE Mit diesem Befehl können Sie sich einen Speicherbereich disassemblieren lassen. Der MegaMon liest dabei die einzelnen Bytes aus und interprtiert sie als As- sembler-Opcodes, deren Textform er auf dem Bildschirm ausgibt. Der Befehl muß von einer Adresse gefolgt sein, ab der disassembliert werden soll. Optional können Sie auch noch eine Endadresse angeben, an der der MegaMon mit der Dis- assemblierung anhalten soll. Geben Sie keine Adresse an, so können Sie den Vor- gang jederzeit mit der 'RUN/STOP'-Taste abbrechen. Hiernach befinden Sie sich automatisch im Assemblier-Modus, in dem Sie ggf. Änderungen in das angezeigte Programm eintragen können und der auf die oben schon genannte Art und Weise beendet wird. Kann der MegaMon einen Bytewert nicht übersetzen, weil es sich z.B. um Daten, oder einen illegalen Op- code handelt, so wird an der entspre- chenden Adresse "???" ausgegeben und an der folgenden Adresse mit der Disassem- blierung fortgefahren. e) "E" - EXCLUSIVE-OR Diese Funktion verknüpft einen Speicher- bereich per Exklusiv-Oder-Operation mit einem Parameterbyte. Sie ist vergleich- bar mit dem Maschinensprache-Befehl "EOR #$XX", wobei "$XX" den zu verknüpfenden Wert darstellt. Als Parameter müssen dem Befehl Anfangs- und Endadresse des zu verknüpfenden Bereichs, sowie das Verknüpfungsbyte übergeben werden. So kann z.B. mit dem Befehl ".E 0400, 07E7,80" der gesamte Bildschirmspeicher invertiert werden. f) "F" - FILL Hiermit kann ein beliebiger Speicherbe- reich mit einem bestimmten Byte-Wert gefüllt werden. Die Syntax entspricht haargenau der des "E"-Befehls. So können Sie z.B. mit ".F 2000,3FFF,00" den Spei- cherbereich, in dem die Grafik-Bitmap im Normalfall zu finden ist, löschen. g) "G" - GO Dieser Befehl springt an eine Adresse, womit Sie ein eigenes Assembler-Programm im Speicher direkt anspringen können. Hierzu können Sie optional eine Sprung- adresse hinter dem Befehl angeben. Tun Sie dies nicht, so wird automatsich die Adresse angesprungen, die im Programm- Zähler stand, als der MegaMon aktiviert wurde. Dies ist besonders hilfreich, wenn Sie ein Programm debuggen. Unter- brechen Sie selbiges nämlich durch einen "BRK"-Befehl, der in den MegaMon ver- zweigt, so enthält der Programm-Zähler die Adresse des Befehls, der nach dem BRK folgen sollte. Durch ein einfaches "G" (ohne Parameter) können Sie so ihr Programm fortfahren lassen. Deshalb legt er auch nicht die Rücksprungadresse auf dem Stapel ab, weswegen Ihr Programm nicht mit "RTS", sondern mit einem "BRK" beendet werden sollte. Andernfalls würde der Prozessor irgendwohin springen und ggf. sogar abstürzen. Der "G"-Befehl ist also im Prinzip mit einem Maschinenspra- che-JMP zu vergleichen. h) "H" - HUNT Diese Funktion dient dem Aufspüren von Bytefolgen in einem bestimmten Speicher- bereich. Hierzu müssen Sie nach dem Be- fehl selbst Start- und Endadresse des zu durchsuchenden Bereichs angeben, gefolgt von einem oder mehreren Bytes, die - in Folge auftretend - gesucht werden sol- len. Angenommen, sie wollten einen Pro- grammteil finden, in dem der Befehl "LDY #$00" steht. Benutzen Sie hierzu zunächst die "A"-Funktion, um herauszu- finden, welchen Opcodes dieser Befehl entspricht. Selbige werden nämlich zwi- schen Adresse und Textdarstellung des Befehls angezeigt. Für den obig genann- ten Befehl ist das der Opcode $A0, ge- folgt von dem Operanden-Byte, das in diesem Fall $00 ist. Geben Sie nun ein- mal die Zeile ".H 8000,8200,A0,00" ein, um in diesem Bereich (in dem der MegaMon ja steht), nach dem LDY-Befehl zu su- chen. Nach kurzer Suchzeit gibt Ihnen der MegaMon die Adressen $804F und $81E0 aus. Schauen Sie sich diese Adressen einmal mit dem "D"-Befehl an, so werden Sie merken, daß sich genau dort die ge- nannten LDY-Befehle befinden. Dies ist übrigens eine Art und Weise, wie man einen Trainer in ein Spiel einbaut (nach LDA/X/Y #AnzahlLeben suchen und Wert verändern). i) "I" - SPEICHERMONITOR Mit dieser Funktion können Sie sich den Inhalt des Speichers anschauen. Sie müs- sen hierzu mindestens die Startadresse und können optional noch die Endadresse des zu untersuchenden Speicherbereichs angeben. Anschließend wird Ihnen der Inhalt des gegebenen Bereichs in je 8 Bytes pro Zeile anzezeigt. Diese Werte sind am Ende der Zeile auch als ASCII- Code zu sehen und können, wie im Kapitel 1 beschrieben, verändert werden. j) "J" - JUMP Dieser Befehl ist ähnlich dem "G"-Befehl und erfordert eine Sprungadresse. Er wird benutzt um eine Unterroutine aufzu- rufen, die mit "RTS" enden muß, damit aus ihr wieder zum MegaMon zurückgekehrt wird. Auf diese Art und Weise rufen Sie also komplette Programme auf, die sie nicht Schritt für Schritt testen möch- ten, sondern die als Ganzes laufen sol- len. k) "M" - MEMORY MAP Dieser Befehl verlangt keine Parameter und gibt Ihnen Auskunft über den Inhalt des gesamten Speichers. Er prüft 256- Byte-Blöcke (sogenannte Pages), ob Sie Daten, oder Nullbytes enthalten. An- schließend gibt der Befehl eine Tabelle aus, in der alle 256 Pages des 64er- Speichers durch einen Stern oder Punkt repräsentiert werden. Links steht dabei das High-Byte der Speicheradresse, und Oben die Nummer der Page dieses Bereichs (jeweils 16 pro $1000-Byte-Block). Enthält ein Eintrag der Tabelle einen Stern ("*"), so befinden sich Daten un- gleich Null in diesem Bereich. Enthält er nur einen Punkt, so sind dort 256 Nullbytes zu finden. l) "N" - RELOCATE MEMORY Mit dieser Funktion können Sie ein Pro- gramm in einem bestimmten Speicherbe- reich "relokieren". Im Klartext heisst das, daß der MegaMon alle absoluten Adressen von Maschinensprache-Befehlen (wie z.B. "LDA $1000", "JMP $202C", "ORA $4711") an eine neue Basisadresse an- passt, so daß das Programm auch in die- sem Bereich lauffähig ist. Ohne Anpas- sung kann man das Programm nämlich nicht einfach so verschieben. Stellen Sie sich vor, Sie hätten ein Programm das an Adresse $1000 liegt und irgendwo mit Hilfe des Befehls "JSR $1088" auf eine Unterroutine springt. Würden Sie jetzt das Programm einfach nach $5000 umkopie- ren, so würde es nach wie vor an Adresse $1088 springen, an der die Unterroutine jedoch nicht mehr vorhanden wäre. Der JSR-Befehl muß also in ein "JSR $5088" modifiziert werden, was der MegaMon mit der "N"-Funktion zu tun vermag. Sie ver- lagt fünf Parameter, die wiefolgt ange- geben werden müssen:
".N 1000,1FFF,4000,1000,1FFF"
Die ersten beiden Werte repräsentieren Start- und Endadresse des zu bearbeiten- den Speicherbereichs. Im Beispiel soll ein Programm im Bereich von $1000 bis $1FFF verschoben werden. Der dritte Pa- rameter ist ein Offset, der auf eine absolute Adresse aufaddiert werden soll. Im Beispiel ist das der Wert $4000, so daß das Programm später an Adresse $5000 lauffähig sein wird. Die letzten beiden Werte geben den Speicherbereich an, in- nerhalb dem sich eine absolute Adresse befinden muß, damit sie verändert wird. In unserem Beispiel ist das der Bereich, in dem das Programm selbst steht, damit alle Sprungbefehle sowie Zugriffsopera- tionen innerhalb dieses Bereichs ange- passt werden. Diese Parameter sind not- wendig, damit der MegaMon zwar den oben schon erwähnten "JSR $1088" in ein "JSR $5000" korrigiert, jedoch nicht einen Aufruf der Betriebssystems-Routine beeinflußt, die ja immer an einer fixen Adresse ist. So bleibt z.B. ein "JSR $FFD2" unverändert, was auch sinngemäß richtig ist. Nach der Relokierung kehrt MegaMon wieder zur Eingabe zurück. Traf er während der Modifizierung auf einen illegalen Opcode, so brach er selbige ab, und zeigt Ihnen nun die fragliche Programmzeile auf disassembliert auf dem Bildschirm an. Achten Sie bitte darauf, daß Sie nur solche Bereiche modifizie- ren, in denen auch tatsächlich ein Pro- gramm steht. Haben Sie nämlich auch Gra- fikdaten oder Tabellen in Ihrem Code eingebettet, so kann es zu Problemen kommen, so daß der MegaMon die Daten falsch interpretiert und deshalb modifi- ziert oder meint er wäre auf einen ille- galen Opcode getroffen. Im Öbrigen ist auch eine negative Ver- schiebung möglich. Sie müssen hierzu einen negativen Verschiebeoffset (der 3. Parameter) im Zweierkomplement-Format angeben. Selbiges entspricht im Prinzip der Rechnung "$FFFF"-Offset. Möchten Sie also den Code um $1000 Bytes nach vorne verschieben, so muß der Offset "$EFFF" angegeben werden. Desweiteren sollte erwähnt werden, daß der MegaMon das Programm nicht im Spei- cher verschiebt, sondern lediglich die Adressen der Befehle verändert. Nach Ausführung des obigen Beispiels steht das Programm also immer noch im Bereich von $1000-$1FFF und muß "von Hand" mit dem "T"-Befehl (s.u.) an Adresse $5000 kopiert werden. Das hat übrigens den Vorteil, daß Sie mit der "N"-Funktion mehrmals über den Code laufen können, um so verschiedene Adressbereiche (die letzten beiden Parameter) zu bearbeiten. (Anm. d. Red.: Bitte wählen Sie jetzt den zweiten Teil der MegaMon-Anleitung aus dem Textmenu.)