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.)