Logic Disassembler
Wer hat nicht schon nach einem guten Einstieg in das Betriebssystem oder in ein selbstgeschriebenes Assembler-Programm gesucht, um dem Verlauf der Programmlogik folgen zu können?
Mit diesem ganz in Basic geschriebenen Programm besteht nun die Möglichkeit, bei einer beliebigen Startadresse einzusteigen und von dort aus das Programm zu verfolgen.
Auch mit einem kompletten Disassembler-Listing war dies bisher eine äußerst aufwendige und zeitraubende Angelegenheit. Bei je dem Sprung-Befehl (sei es BRANCH, JSR oder JMP) ging das große Blättern los. Das Verfolgen von mehrstufigen Unterroutinen mit unterschiedlichen Ausstiegsmöglichkeiten ist schon ganz unmöglich.
Der Logic-Disassembler hingegen wartet bei jedem Sprungbefehl auf die Eingabe von Y, N oder X. Y steht für »yes«, das heißt dem Sprungbefehl folgen, N steht für »no«, also zum Beispiel eine bekannte Unterroutine einfach zu übergehen, damit das Listing nicht zu unübersichtlich wird. X schließlich steht für »exit«, wodurch der Disassembler bei einer neuen Adresse gestartet werden kann.
Das Listing der Basic-Routine »NEW« (Bild 1) zeigt als Beispiel, wie ein solcher Disassembler-Lauf vor sich geht.
Die Einsprungadresse liegt bei $C642.
In Zeile 1 wird der BNE-Befehl mit der Eingabe von »N« übergangen. Der JSR-Befehl in Zeile 14 wird mit »Y« verfolgt, und es erfolgt eine Verzweigung in die Routine $C68E. Mit der Anzeige von STACK 0 wird über die Tiefe der Unterprogramm-Verschachtelung informiert. Bei Erreichen von RTS in Zeile 22 wird in das Hauptprogramm (STACK 0) zurückgesprungen und dieses ab der Adresse $C65C fortgeführt.
Der darauffolgende BRANCH-Befehl in Zeile 24 wird wieder mit der Eingabe von »N« übergangen. In Zeile 25 folgt dann ein RTS, und da der STACK auf 0 steht (man befindet sich also im Hauptprogramm), wird der Disassembler-Vorgang beendet und auf die erneute Eingabe einer Startadresse gewartet.
Bei der Eingabe von »END« statt einer Startadresse wird das Programm beendet.
Dabei wird jede Stackänderung angezeigt.
Es können alle Sprungbefehle verfolgt werden, sogar solche, die sich auf eine indirekte Adressierung beziehen. Als Beispiel hierfür kann das Disassembler-Protokoll der Abfrage der Stop-Taste dienen (Bild 2).
In der Zeile 1 ist der Befehl JMP ($0328) gefunden worden, jetzt wird der Inhalt der Speicherstelle $0328 und $0329 ausgelesen und die Sprungadresse errechnet. Dann erfolgt ein Speichertest an der errechneten Sprungadresse, und erst, wenn dieser Test positiv verläuft, wird ab dieser Adresse weiter disassembliert. Verläuft der Test jedoch negativ, erfolgt ein »LOGIC FLOW ERROR«, und es wird zum Ende der Disassemblierung gesprungen.
Das Programm »Logic-Disassembler« ist in der vorliegenden Form für den VC 20 geschrieben, es ist jedoch nach Änderung der Zeilen 100 und 530 (die POKE-Befehle ändern lediglich die Farben des Bildschirms) sofort auf dem Commodore 64 und den anderen CBM-Computern lauffähig.
(Fred Hammer)A$ | Tabelle für Sprungadressen |
AC% | Tabelle für 6502-Mnemonics |
SS% | Tabelle für Stack |
SS% | Index für Stack |
I | Index für Mnemonic-Tabelle |
H$ | Werte für Hexa-Umrechnung |
FE$ | Zwischenspeicher für Anfangsadresse |
A$ | Startadresse in Hexa |
X$ | Hexa-Wert bei Umrechnung |
DE | Dezimal-Wert bei Umrechnung |
Z0 N0 Z1 |
Indexfelder für Umrechnung |
A | Anfangsadresse ln Dezimal |
AN$ | KZ für Druckerausgabe |
N | Zeilennummer |
AD | aktuelle Adresse bei der Disassemblierung |
P | Zwischenspeicher für Adreßrechnung |
EA | Dezimal-Wert des laufenden Befhles |
S$ | Hexa-Werte der laufenden Disassembler-Zeile |
MN$ | laufende Disassembler Zeile |
K | Anzahl der Bytes für das Befehlswort |
AA$ | Eingabefeld bei Sprungbefehlen |
FF$ | Überschrift bei Druckerausgabe |
A1 | Arbeitsfeld zur Adreßberechnung bei JMP ind. |
A2 | wie A1, jedoch zur Kontrolle ob Memory vorhanden |
100-250 | Programmstart und Tabelleninitialisierung |
260-290 | Umrechnung Hexa in Dezimal |
300-350 | Umrechnung Dezimal in Hexa |
360-510 | DATA-Satements mit den 6502-Mnemonics |
520-550 | Eingabe der Startadresse |
560-620 | Abfrage auf Druckerausgabe |
630-870 | Disassembler—Schleife |
880-970 | BRANCH-Befehle |
980-1040 | Eingabe (Y)es, (N)o, e(X)it |
1050-1080 | RTS-Befehl mit Stack-Abfrage |
1090-1170 | JSR-Befehl mit Stack-Erhoehung |
1180-1200 | JMP-Befehl absolut |
1210-1250 | JMP-Befehl indirekt |
1260-1300 | Ende |