MEGAMON - Speichermonitor für Assemblerfreaks -
Wer Assembler programmiert kennt sie:
die Speichermonitore, mit denen man
schnell mal was assemblieren oder disassemblieren, oder kurz einen Blick in den
Speicher wagen kann. Ein jeder Maschinensprache- Coder kommt nicht um ein
solch nützliches Programm herum, das
viele Funktionen zur Unterstützung der
täglichen Programmier-Arbeit bereitstellt. Auch wir von der MagicDisk wollen Ihnen nun ein solches Programm vorstellen: 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 Verwendung findet) zu verfügen, um die
Funktionsweise des Programms zu verstehen. Da dies hier eine Programmanleitung
ist, und kein Assembler-Kurs, muß ich
Sie diesbezüglich leider auf entsprechende Literatur verweisen. Die Anleitung geht davon aus, daß Sie sich mit
den Assembler-Befehlen, sowie Speicheraufteilung 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 auftreten. BRK-Interrupts sind softwaremässige
Unterbrechungen, die der Prozessor
selbst erzeugt, sobald er auf den Assembler- 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 insbersondere nützlich, wenn Sie das Programm zum Austesten eigener Programme
benutzen möchten. Nachdem der MegaMon
initialisiert wurde, können Sie in Ihrem
eingenen Programm einen BRK-Befehl einsetzen und selbiges starten. Erreicht
der Prozessor nun den BRK-Befehl, so
springt er sofort in den MegaMon, der
Ihnen den Status des Prozessors und seiner Register anzeigt, womit Sie prüfen
können, welche Werte Ihr Programm gerade
am Bearbeiten war, und in welchem Zustand es sich befand. Die einzelnen Werte 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 Carryoder Zero-Bit zum Zeitpunkt 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) eingeben müssen. Alle Befehle werden durch
einen einzelnen Buchstaben ausgedrückt, dem je nach Funktion einer oder mehrere
Parameter nachgestellt sein können. Selbige werden IMMER mit Kommata voneinander getrennt. Desweiteren muß dem Befehlsbuchstaben immer ein Punkt voranstehen, damit er erkannt wird. Da Sie im
MegaMon genauso über den Bildschirm fahren können, wie im normalen Basic-Editor
des C64, können Sie so auch jede beliebige 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 Ihnen irgendwelche Speicher-, Registeroder 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 MegaMon 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 Buchstaben repräsentiert, der je nach Befehl
von einem oder mehreren Parametern gefolgt 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 sogleich übersetzt werden und als Assembler- Opcodes in den Speicher geschrieben
werden. Hierzu müssen Sie dem " A" eine
Adresse nachstellen, an die assembliert, sowie den Assembler-Befehl, der an dieser 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 Befehle ( ohne " A"+ Adresse) einzugeben.
Versteht er einen Ihrer Befehle nicht, so bricht er den Assemble-Modus ab, und
gibt ein Fragezeichen hinter der besagten 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 Zahlwerten IMMER hexazedimale Zahlen verlangt, denen Sie ein "$"- Zeichen voransetzen müssen. Ohne dieses Zeichen verweigert der MegaMon die Annahme des entsprechenden 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 Inhalt zweier Speicherbereiche miteinander
vergleichen. Geben Sie hierzu die Startund Endadresse des ersten Bereichs, sowie die Startadresse des zweiten Bereichs an, jeweils durch Kommata voneinander getrennt ( z. B." . C 2000,20 FF,3000- vergleicht den Inhalt des Speicherbereichs von $2000 bis $20 FF mit dem Inhalt ab $3000) . Der MegaMon vergleicht nun jedes einzelne Byte des ersten Bereichs, mit dem entsprechenden Byte des
zweiten Bereichs und gibt Ihnen bei
Nicht-Öbereinstimmung die Adresse aus, an der sich zwei Bytes voneinander unterscheiden. Dies tut er für alle Bytes
des angegebenen Bereichs, bevor er wieder in den Kommandozeilen-Modus zurückkehrt.
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 Assembler- 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 Disassemblierung anhalten soll. Geben Sie
keine Adresse an, so können Sie den Vorgang 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 Opcode handelt, so wird an der entsprechenden Adresse " ? ? ?" ausgegeben und an
der folgenden Adresse mit der Disassemblierung fortgefahren.
e)" E"- EXCLUSIVE-OR Diese Funktion verknüpft einen Speicherbereich per Exklusiv-Oder- Operation mit
einem Parameterbyte. Sie ist vergleichbar mit dem Maschinensprache-Befehl " EOR
#$ XX", wobei "$ XX" den zu verknüpfenden
Wert darstellt. Als Parameter müssen dem
Befehl Anfangsund Endadresse des zu
verknüpfenden Bereichs, sowie das
Verknüpfungsbyte übergeben werden. So
kann z. B. mit dem Befehl " . E 0400,
07 E7,80" der gesamte Bildschirmspeicher
invertiert werden.
f)" F"- FILL Hiermit kann ein beliebiger Speicherbereich 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,3 FFF,00" den Speicherbereich, 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 Sprungadresse 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. Unterbrechen Sie selbiges nämlich durch einen" BRK"- Befehl, der in den MegaMon verzweigt, 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 Maschinensprache- JMP zu vergleichen.
h)" H"- HUNT Diese Funktion dient dem Aufspüren von
Bytefolgen in einem bestimmten Speicherbereich. Hierzu müssen Sie nach dem Befehl selbst Startund Endadresse des zu
durchsuchenden Bereichs angeben, gefolgt
von einem oder mehreren Bytes, die - in
Folge auftretend - gesucht werden sollen. Angenommen, sie wollten einen Pro- grammteil finden, in dem der Befehl " LDY
#$00" steht. Benutzen Sie hierzu
zunächst die " A"- Funktion, um herauszufinden, welchen Opcodes dieser Befehl
entspricht. Selbige werden nämlich zwischen Adresse und Textdarstellung des
Befehls angezeigt. Für den obig genannten Befehl ist das der Opcode $ A0, gefolgt von dem Operanden-Byte, das in
diesem Fall $00 ist. Geben Sie nun einmal die Zeile " . H 8000,8200, A0,00" ein, um in diesem Bereich ( in dem der MegaMon
ja steht), nach dem LDY-Befehl zu suchen. Nach kurzer Suchzeit gibt Ihnen
der MegaMon die Adressen $804 F und $81 E0 aus. Schauen Sie sich diese Adressen
einmal mit dem " D"- Befehl an, so werden
Sie merken, daß sich genau dort die genannten 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üssen 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 aufzurufen, 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öchten, sondern die als Ganzes laufen sollen.
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. Anschließend gibt der Befehl eine Tabelle
aus, in der alle 256 Pages des 64 er-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 ungleich 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 Programm in einem bestimmten Speicherbereich " relokieren" . Im Klartext heisst das, daß der MegaMon alle absoluten
Adressen von Maschinensprache-Befehlen
( wie z. B." LDA $1000"," JMP $202 C"," ORA
$4711") an eine neue Basisadresse anpasst, so daß das Programm auch in diesem Bereich lauffähig ist. Ohne Anpassung 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 umkopieren, 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 verlagt fünf Parameter, die wiefolgt angegeben werden müssen:
".N 1000,1FFF,4000,1000,1FFF"
Die ersten beiden Werte repräsentieren
Startund Endadresse des zu bearbeitenden Speicherbereichs. Im Beispiel soll
ein Programm im Bereich von $1000 bis
$1 FFF verschoben werden. Der dritte Parameter 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, innerhalb 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 Zugriffsoperationen innerhalb dieses Bereichs angepasst werden. Diese Parameter sind notwendig, 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 modifizieren, in denen auch tatsächlich ein Programm steht. Haben Sie nämlich auch Grafikdaten oder Tabellen in Ihrem Code
eingebettet, so kann es zu Problemen
kommen, so daß der MegaMon die Daten
falsch interpretiert und deshalb modifiziert oder meint er wäre auf einen illegalen Opcode getroffen.
Im Öbrigen ist auch eine negative Verschiebung 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 Speicher 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-$1 FFF 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.)