Letzte Warnung vor DEBUG

Wir möchten die Gelegenheit nutzen, und Sie zum ersten und letzten Mal vor voreiligen, unüberlegten und wirklich gefährlichen DEBUG-Aktionen warnen.

Wenn Sie nicht ausgeschlafen haben oder überhaupt unsicher sind, unterlassen Sie lieber jede direkte Aktion mit DEBUG. Plötzlich brachliegende Disketten oder Festplatten sind noch das harmloseste Problem. Falscheingaben können unter Umständen echte Hardware-Schäden hervorrufen. Besonders Hercules-Grafikkarten reagieren sehr empfindlich, wenn bestimmte Register falsche Werte serviert bekommen.

Wie bereits erwähnt, ist unser erstes Beispiel noch kein richtiges Assemblerprogramm, sondern nur die Verwendung einer Funktion innerhalb unseres Debuggers: Nämlich an eine bestimmte Stelle des Arbeitsspeichers im PC (FFFF:0) zu »gehen« (g steht für go) und dort eine bereits vorhandene Routine auszuführen. Nützlich wäre es doch jetzt, solche »Dienstleistungen« als Programm, genau wie Stapeljobs abzuspeichern, um es bei Bedarf zu starten – ohne zusätzlich Tastatureingaben in DEBUG tätigen zu müssen.

Als DEBUG-Eingabedatei, also nicht als Eingabe in DEBUG, sondern als eine mit einem beliebigen Texteditor kreiierte ASCII-Datei, könnte dieser Aufruf genauso wie im ersten Beispiel aussehen:

G=FFFF:0

Speichern Sie diese Zeile unter dem Namen RESET.DEB ab. Wenn Sie jetzt »DEBUG <RESET.DEB« eingeben, erleben Sie den gleichen Systemstart wie zuvor, diesmal jedoch außerhalb Debuggers.

Diesen Einzeiler jetzt ein Assemblerprogramm zu nennen, wäre noch immer maßlos übertrieben. Um diesem Titel gerecht zu werden, muß die Zeile aus »echten« Assembleranweisungen bestehen, und nicht wie bisher etwa aus speziellen DEBUG-Kommandos. Mischen wir RESET.DEB mit DEBUG-Anweisungen und Mnemonics:

A
JMP FFFF:0

RCX
5
NRESET.COM
W
Q

Achten Sie bei der Eingabe unbedingt auf die Leerzeile vor dem RCX-Befehl! Da die Routine nach ihrer Ausführung mit einem Reset endet und eine sofortige Rückkehr auf die DOS-Ebene nicht zu erwarten ist, brauchen Sie sich ausnahmsweise um das Programmende, das spätesten vor dem RCX-Befehl notwendig wäre, nicht zu kümmern. A ist ein DEBUG-Kommando und bedeutet »Assembliere« die folgenden Zeilen. JMP ist ein Mnemonic (Assemblerbefehl) des durch die Firma Intel ins Leben gerufenen Mikroprozessors der 80×86-Serie. Die Abkürzung steht für »Jump« und bedeutet springen. Nämlich an die Speicherstelle, die Sie hinter JMP hexadezimal eingeben haben (FFFF:0). Dort befindet sich wie bereits erwähnt die DOS-Routine für die Durchführung eines Systemstarts. »RCX« kündigt die Änderung des Wertes im Register CX (RCX = Register CX) an. Eine Zeile später erhält das Register CX – beim Speichern verantwortlich für die Programmlänge – den Wert 5. »NRESET.COM« bedeutet »Name = RESET.COM«. »W« steht für »Write« und schreibt das per »N«-Befehl eine Zeile zuvor benannte Programm, dessen Länge 5 Byte (RCX) beträgt, auf den aktuellen Datenträger. »Q« beendet die DEBUG-Sitzung und veranlaßt eine Rückkehr auf die DOS-Ebene.

Übersetzen Sie das Programm mit der Eingabe »DEBUG <RESET.DEB«. Auf einen Systemstart können Sie jetzt vergeblich warten. Erst wenn Sie »RESET« eingeben, startet das ausführbare Programm RESET.COM – der PC verabschiedet sich wieder für eine Weile. Nach diesem Beispiel können wir unsere erste Schlußfolgerung ziehen. Mit DEBUG lassen sich ausführbare COM-Programme erzeugen, die sich entweder direkt in den Debugger eingeben oder aus einer Eingabedatei übersetzen lassen.

Der Umgang mit Maschinensprache umfaßt natürlich nicht nur das Auslösen von Resets. Alles, was in höheren Programmiersprachen möglich ist, läßt sich auch in Assembler und damit auch in DEBUG bewerkstelligen – allerdings mit erheblich mehr Aufwand. Was bedeutet »mehr Aufwand«? Unser nächstes Beispiel wird es Ihnen verdeutlichen. Ein kurzes akustisches Signal auf dem PC zu erzeugen, könnte in Turbo-Pascal beispielsweise so aussehen:

Begin
 Sound(750);
 Delay(100);
 NoSound;
End.

Das Programm ist kurz und durch Verwendung sinnentsprechender Befehle leicht verständlich. In Assembler müssen Sie die drei bequemen Anweisungen Sound, Delay (Verzögerung) und NoSound Byte für Byte selbst machen. Speichern Sie die folgenden Zeilen unter dem Namen SOUND.DEB ab. Achten Sie bei der Eingabe wieder auf die Leerzeile vor dem RCX-Befehl. Da die Routine etwas länger ist, teilen wir Ihnen vorsichtshalber die Prüfsumme mit, die Sie mit dem Programm CHKSUM.DEB im Kapitel » … « überprüfen können: 4012. Außerdem finden Sie am Ende der entscheidenden Programmzeilen ein Zahl, auf die wir gleich zurückkommen werden. Ob Sie sie eingeben oder nicht, bleibt Ihnen überlassen.

A
MOV  BX,02EE        ;100
MOV  AX,34DD        ;103
MOV  DX,0012        ;106
CMP  DX,BX          ;109
JNB  0132           ;10B
DIV  BX             ;10D
MOV  BX,AX          ;10F
IN   AL,61          ;111
TEST AL,03          ;113
JNZ  011F           ;115
OR   AL,03          ;117
OUT  61,AL          ;119
MOV  AL,B6          ;11B
OUT  43,AL          ;11D
MOV  AL,BL          ;11F
OUT  42,AL          ;121
MOV  AL,BH          ;123
OUT  42,AL          ;125
MOV  CX,FFFF        ;127
LOOP 012A           ;12A
IN   AL,61          ;12C
AND  AL,FC          ;12E
OUT  61,AL          ;130
RET                 ;132

RCX
33
NSOUND.COM
W
Q

SOUND.DEB erzeugt ein akustisches Signal völlig »zu Fuß« – Byte für Byte. Das Programm ist im Prinzip mit der Turbo-Pascal-Routine identisch. Es ist doch erstaunlich, was sich alles hinter den Pascal-Befehlen »Sound«, »Delay« und »NoSound« verbirgt. Hexadezimale Zahlen werden in Register wie zum Beispiel AX, BX oder DX »geschoben« (MOVe), mit anderen Werten verglichen (CoMPare) und an bestimmte, für den Lautsprecher verantwortliche Speicherzellen ausgegeben (OUT). Aus »Delay« ist eine Schleife (LOOP) geworden, die solange durchlaufen wird, bis das Register CX den Wert Null erreicht hat. »NoSound« wird durch drei Assemblerzeilen vor dem RET-Befehl realisiert, der das Programm beendet und für die Rückkehr auf die DOS-Ebene sorgt.

Quelle: 200 Utilities für PC-/MS-DOS von Gerhard Schild und Thomas Jannot