Home

Programmbeispiel zum Assemblieren mit DEBUG

Zurück zur Assemblerauswahlseite

8086 Assembler (MS-DOS):
Der Debugger DEBUG

Debug ist ein Testhilfsprogramm zum Bearbeiten, Ändern und Testen von Binär-(Programm-)Dateien. Die Ausführung jedes DEBUG-Befehles kann durch Strg-C oder Strg-BREAK abgebrochen werden. Mit Strg-S kann die Bildschirmausgabe angehalten werden.

Wie alle Testhilfsprogramme erfordert die Anwendung eine gewisse Übung. Eine andere Möglichkeit, Assemblerprogramme ohne solche Testhilfsprogramme zu "debuggen", ist die Verwendung spezieller Testmakros oder -unterprogramme. Auf der Seite  i Routinensammlung für COM-Programme sind mit den Macros RDUMP und MDUMP zwei Anzeigeroutinen enthalten, die speziell zum Testen der Programme gedacht sind. Auf der Seite  i Statt DEBUG: Demonstration von RDUMP und MDUMP wird die Anwendung dieser beiden Macros an einem Beispiel gezeigt.

Aufruf:
DEBUG
DEBUG /?
DEBUG [Datei][.Erw][Argliste]

Aufruf ohne Parameter: DEBUG antwortet mit dem Bereitschaftszeichen - und erwartet die Eingabe von Befehlen. Man kann mit dem aktuellen Speicher, mit Disk-Sektoren oder Disk-Dateien arbeiten.

DEBUG /? zeigt eine Hilfsanzeige.

Vermeiden Sie einen Neustart des Programmes nach der Meldung
Program terminated normally.
Statt dessen müssen Sie das Programm mit den Befehlen Name oder Load neu laden, um es erneut starten zu können.

Aufruf mit Parametern: Hierbei wird die Datei in den Speicher geladen. Es wird ein Programmkopf ab Adresse 0 eingerichtet. Wird eine .COM- oder .EXE- Datei angegeben, so darf der Programmkopf unterhalb der Adresse 5CH nicht verändert werden (andernfalls wird DEBUG beendet). Die Argliste versorgt das bei Datei angegebene Programm.

Kommandostruktur: Jedes DEBUG-Kommandos besteht aus einem Buchstaben, der von einem oder mehreren Parametern gefolgt sein kann. Bei formal falschen Kommandos erscheint als Fehlerindikator das Zeichen ^ gefolgt von dem Wort Error.

Fehlermeldungen:  i Fehlermeldungen bei Debug

Befehl Syntax Funktion
Assemble a [Adresse] Befehle assemblieren
Compare c Bereich Adresse Befehle vergleichen
Dump d [Bereich] Speicher hexa zeigen
Enter e Adresse [Liste] Daten eingeben
Fill f Adresse Liste Bereich füllen
Go g[=Adresse[Adresse...]] Programm starten, ggf. mit Breakpoints
Hex h Wert Wert] Hexadezimalzahlen berechnen
Input i Portadresse] von Portadresse lesen
Load l [Adresse [Laufwerk Sektor Sektor]] Datei oder Sektor laden
Move m Bereich Adresse]  i Bereich kopieren
Name n [Laufwerk:][Pfad]Datei[.Erw][...]  i Dateinamen und/oder Parameter festlegen
Output o Portadresse Wert] auf Portadresse schreiben
Procstep p[=Adresse[Anzahl]] Programmschrittausführen
Quit q DEBUG beenden
Register r [Registername] Registerbelegung zeigen/ ändern
Search s Bereich Liste] Bytes suchen
Trace t[=Adresse][Wert] Verfolge Programmablauf
Unassemble u [Bereich] Befehle disassemblieren
Write w [Adresse[Laufwerk:Satz Satz]]  i Datei oder Sektor schreiben
? Hilfsanzeige Zeigt die möglichen DEBUG-Kommandos an.
Im Sinne dieser Befehlsbeschreibung sind:
Adresse: ein zweiteiliger Parameter, bestehend aus einer alphabetischen Segmentangabe oder einer vierstelligen Segmentadresse und einem Offset-Wert. Segmentangabe und Segmentadresse können weggelassen werden. Defaultwerte sind DS für Datenwerte, sonst CS.
Beispiele:CS:0100
04B4:0100

Bereich: Ist ein Parameter, der aus zwei Adressen besteht. Sein Aufbau ist entweder
Adresse-von Adresse-bis
Adresse-von L Wert

Wert ist die Zeichenanzahl auf die der Befehl wirken soll.
Beispiele: CS:100 110
CS:100 L 10

Laufwerk: Bei der Laufwerksangabe sind die Werte 0 bis 3 zugelassen. 0=A, 1=B, 2=C, 3=D

A Assembliert Anweisungen sofort nach der letzten Eingabe in den Speicher an der aktuellen Adresse. Die Eingabe von ENTER beendet die Eingabe.

Aadresse Assembliert Anweisungen mit der Adresse beginnend in den Speicher.
A100 Die Eingabe von ENTER beendet die Eingabe. Cbereich adresse vergleicht zwei Speicherblöcke.
C100 L20 200 vergleicht 32 Bytes ab Adresse 100 mit 32 Bytes ab Adresse 200

D Zeigt den Inhalt des Speichers beginnend ab der zuletzt gezeigten Position.

Dadresse Zeigt den Inhalt des Speichers beginnend ab der angegebenen Position.
D650

Dbereich Zeigt den Inhalt des Speichers beginnend ab der angegebenen
D650 L50 Position in der angegebenen Länge
D650 6A0 bzw. von Adresse bis Adresse.

Eadresse Beginn der Eingabe von HEX-Werten ab Adresse.
EDS:50 Eingabebeginn bei Datensegment:50h
Die Eingabe erfolgt bis ENTER gedrückt wird. Space überspringt ein Byte.

Eadresse liste Gibt die Byte liste in den Speicher beginnend an der angegebenen Adresse.
E100 20 20 Gibt zwei Leerzeichen ab Adresse 100h im aktuellen Segment ein.

Fadresse Liste Füllt Speicherbereich ab der angegebenen Adresse mit Bytewerten aus der Liste.
FDS:00 L0F "TEH" Ab Adresse 00 im Datensegment wird 5-mal, d.h. 0fh Bytes lang, die Bytefolgen TEH eingefüllt.

G Beginnt die Ausführung bei der aktuellen Adresse CS:IP

G=adresse Beginnt die Ausführung bei der angegebenen Adresse
G=100 Beginnt auf Adresse 100H im aktuellen CS

G=adresse adressleiste Beginnt Ausführung ab Adresse mit in der Adressleiste angegeben Breakpoints.
G=100 10A 213 Beginnt auf Adresse 100H im aktuellen CS mit Breaks wenn Adresse 10AH oder 213H erreicht ist.

H wert wert Hexadezimalzahlen berechnen
H 8 0F Addiert und subtrahiert 8H und FH, zeigt die Ergebnisse an.

I portadresse von Portadresse lesen
I 2E6 liest von Port 2E6H ein, zeigt gelesenen Wert an.

L Lädt Datei (deren Spezifikation bei CS:80H steht) nach CS:100H

L adresse Lädt Datei (deren Spezifikation bei CS:80H steht) nach Adresse.
COM- und EXE-Dateien werden jedoch immer nach CS:100H geladen.
L 506 Lädt Datei (deren Spezifikation bei CS:80H steht) nach CS:506H
L Adresse Laufwerk Sektor1 Sektor2 Lädt Sektoren aus dem Laufwerk in die Adresse beginnend ab Sektor1 in der Anzahl Sektor2. Die Sektoranzahl ist maximal 80H. Nach dem L-Befehl sind die Register BX:CX auf die Anzahl gelesener Bytes gesetzt.
L DS:10 2 0 3 Lädt die ersten 3 Sektoren von Laufwerk C: nach DS:10H

M bereich adresse  i Kopiert den angegebenen Bereich an die neue Adresse. Die Übertragung wird ohne Speicherverlust durchgeführt.
M 100 L10 500 Kopiert 16 Bytes ab Adresse 100H nach 500H.

N dateiname  i Der Dateiname wird auf Adresse CS:80H eingetragen. Auch die Übergabe von Parametern ist hier möglich.
N c:irgend.was c:irgend.was wird für den Debugger vorbereitet.

O portadresse wert Schreibt den Wert zur Portadresse.
O 2E6 FF Schickt FFH zum Port 2E6H

P Hält die Ausführung einer Instruktion bei der nächsten Instruktion an. Die Ausführung beginnt bei CS:IP Die P- Anweisung hat dieselbe Syntax wie T(race)
P=Adresse Ausführung von Adresse bis zum Ende der betreffenden Anweisung.
P=1044 Ausführung beginnt bei Adresse CS:1044
P=Adresse Anzahl Anweisung von Adresse bis soviel Bytes abgearbeitet sind, wie bei Anzahl angegeben.
P=1044 10 Ab CS:1044 werden 16 Bytes abgearbeitet.

Q Debug wird sofort beendet, ohne dass irgendetwas gesichert wird.

R zeigt alle Register an.
R register zeigt den Inhalt des Registers an und ermöglicht seine Änderung.
Registernamen: AX BX CX DX SP BP SI DI DS ES SS CS IP PC F
Wird F als Registername angegeben, so werden alle CPU-Flags mit einem 2 Zeichen langen Namen, der den Zustand der betreffenden Flag wiedergibt, gezeigt. Um eine Flag zu ändern, muss einer der Setz- oder Löschcodes bei der Bereitschaftsanzeige eingegeben werden:

Flag setzen löschen
Überlauf OV ja NV nein
Richtung DN dekrement UP increment
Interrupt EI enable DI disable
Vorzeichen NG negativ PL positiv
Null ZR ja NZ nein
Zus. Carry AC ja NA nein
Parität PE even PO odd
Carry CY ja CY nein

R AX zeigt Inhalt von AX und wartet auf neue Werte. Die Eingabe von ENTER lässt den Inhalt unverändert.

S bereich liste Durchsucht den Speicherbereich nach Listinhalten.
S 100 L100 "TEH"Sucht nach dem Muster TEH in den 100H Bytes ab Adresse CS:100H
S CS:100 200 41 Sucht nach dem Byte 41H in den 200H Bytes ab Adresse CS:100H

T Führt eine Anweisung im Einzelschritt durch. Die Ausführung beginnt bei CS:IP.
T=adresse Führt eine Anweisung im Einzelschritt ab der angegebenen Adresse aus.
T=1044 Ausführung beginnt bei Adresse CS:1044
T=adresse anzahl Anweisung ausführen ab Adresse bis soviel Bytes abgearbeitet sind, wie bei Anzahl angegeben.
0bei Anzahl bedeutet alles.
T=100 10 Ab CS:100 werden 16 Bytes abgearbeitet.

Unassemble
u [Bereich] Befehle disassemblieren

Write

w [adresse[laufwerk:satz satz]]  i Datei oder Sektor schreiben.

Eigenschaften und Unterschiede zum Macroassembler MASM

  • DEBUG kennt keine Pseudo-Ops wie ORG und ASSUME.
  • DEBUG verarbeitet lediglich DW und DB. DW assembliert Byte-Werte, DW assembliert Wort-Werte direkt in den Speicher.
    debug
    -a
    151A:0100 db 1,2,3,"Dies ist ein Beispiel"
    151A:0118 db 'ein Anführungszeichen:"'," und ein Apostroph:'"
    151A:0143 dw 1000,2000,"ABC"
    151A:014A
    -d100 149
    151A:0100  01 02 03 44 69 65 73 20-69 73 74 20 65 69 6E 20   ...Dies ist ein
    151A:0110  42 65 69 73 70 69 65 6C-65 69 6E 20 41 6E 66 81   Beispielein Anf.
    151A:0120  68 72 75 6E 67 73 7A 65-69 63 68 65 6E 3A 22 20   hrungszeichen:"
    151A:0130  75 6E 64 20 65 69 6E 20-41 70 6F 73 74 72 6F 70   und ein Apostrop
    151A:0140  68 3A 27 00 10 00 20 41-42 43                     h:'... ABC
    -
    
  • DEBUG erkennt keine PSEUDO-Argumente. So wird zur Unterscheidung für Wort- und Byte Operationen ein W oder B beim Mnemonics verwendet:
    CMPS -> CMPSB / CMPSW
    analog bei: LODS, MOVS, SCAS, STOS
  • DEBUG unterscheidet automatisch zwischen Wort- und Byte Operationen
    MOV AL,41 ;Byte
    MOV AX,41 ;Wort
    MOV AL,0041 ;falsch, 0041 ist ein Wort
  • DEBUG kann nicht automatisch unterscheiden, ob sich ein Operand auf eine Wort- oder Byteadresse bezieht. Gegebenenfalls muss der Dateityp explizit mit dem Präfix WORD PTR oder BYTE PTR angegeben werden (Abgekürzt WO oder BY).
    DEC [/ZAEHLER/] ist mit [/ZAEHLER/] ein Byte oder ein Wort gemeint? Beispiel:
    NEG BYTE PTR [128]
    DEC BYTE [/ZAEHLER/]
    Dies gilt für: ADD/ADC, AND, DEC, DIV, IDIV, IMUL, INC, MOV, MUL, NEG, NOT,OR, SUB/SBB, TEST und XOR.
  • DEBUG kann nicht anhand des Arguments die Adressierungsart erkennen.
    MASM: DEBUG: bei MASM:
    MOV AL,HALLO MOV AL,41 HALLO EQU 41H
    MOV AL,HALLO MOV AL,[41] HALLO LABEL NEAR
  • DEBUG kann nicht automatisch unterscheiden, ob sich ein Operand auf einen Speicherplatz oder eine Direktoperanden bezieht. Es gilt: In eckige Klammern angegebene Operanden beziehen sich auf Speicherplätze. Beispiel:
    MOV AX, 21 ;lade AX mit 0021h
    MOV AX,[21] ;lade AX mit dem Inhalt des Speicherplatzes 0021h
  • DEBUG arbeitet in RADIX 16
  • DEBUG versteht den vorgezogenen Segment Override Prefix, z.B.:
    CS:XLAT
    CS:MOV AX,[DI] dagegen:MOV AX,CS:[DI] ;beim MASM
  • Der Assembler von DEBUG erzeugt automatisch kurze, nahe oder ferne Sprünge/ Unterprogrammaufrufe. Diese Automatik kann durch die Verwendung der Präfixe NEAR und FAR überschrieben werden. NEAR kann als NE abgekürzt werden. Beispiel:
    0100:0500 JMP 502 ;erzeugt einen 2-Byte Sprung (kurz)
    0100:0500 JMP NEAR 502 ;erzeugt einen 3-Byte Sprung (near)
    0100:0500 JMP FAR 502 ;erzeugt einen 5-Byte Sprung (fern)
  • DEBUG benötigt keinen Offset-Operator und erkennt automatisch, dass mit MOV BX,/TABLE/ der Offset gemeint ist. MASM meldet hier mit 'illegal size for item' dass die 20-bit-Adresse von /TABLE/ nicht ins Register BX hineinpasst.
  • DEBUG kennt alle Formen der indirekten Registeradressierung. Beispiel:
    ADD BX,34[BP+2].[SI-1]
    POP [BP+DI]
    PUSH [SI]
  • DEBUG kennt Operationscode-Synonyme. Beispiel:
    LOOPZ 100
    LOOPE 100
  • Für die 8087-Befehle müssen ggf. die Präfixe WAIT und FWAIT angegeben werden. Beispiel:
    FWAIT FADD ST,ST(3)

DEVICE

Reservierte Gerätenamen sind:
AUX: oder
COM1:1.serielle Schnittstelle
COM2:2.serielle Schnittstelle
COM3:3. " "
COM4:4. " "
CON: Konsole (Tastatur und Bildschirm)
PRN: oder
LPT1:1. Paralleldrucker
LPT2:2. " "
LPT3:3. " "
NUL: Scheingerät

1. Beispiel einer Debug-Sitzung

Das kleine Programm schreibt die Zeichen ABCDEFGH auf den Bildschirm. Schwarzer Text: Eingaben und Anzeigen. Roter Text: Kommentare.
0:10:35:14 C:\>debug Programmaufruf von "DEBUG"
-a Aufruf des Assemblers
151A:0100 mov cl,10 Eingabe erster Befehl
151A:0102 mov dl,41 41 ist der ASCII-Code von "A"
151A:0104 mov ah,2 Interrupt Zeichenausgabe vorbereiten
151A:0106 int 21 Interrupt Zeichenausgabe ausführen
151A:0108 inc dl ASCII-Code um 1 erhöhen
151A:010A dec cl
151A:010C jnz 104 und das 16-mal (wie in cl angegeben)
151A:010E mov ah,4c Programm beenden!
151A:0110 int 21
151A:0112
-r Prüfen der Registerstände
AX=0000 BX=0000 CX=0000 DX=00
DS=151A ES=151A SS=151A CS=15
-rcx Vorbereiten Schreiben 256 Bytes
CX 0000 BX enthält bereits 0000
:100 CX bekommt 0100 als Wert
-n c:\abc.com Festlegen Dateiname
-w Scheiben der Datei abc.com auf Platte
00100 Bytes werden geschrieben
-g Start des Testlaufs
ABCDEFGHIJKLMNOP Ausgabe des Textprogramms,
0:10:46:29 C:\>gleichzeitig Programmende
Das mit dem Debugger assemblierte Programm steht als Datei abc.com auf der Platte, allerdings ist die Datei mit 256 Bytes Länge etwas zu lang. Vor dem Schreiben des Programmes muss man unbedingt das Doppelregisterpaar BX und CX auf die Anzahl der gewünschten Programmlänge setzten. Bei praktikablen Programmlängen ist BX immer 0000. Besonders wichtig ist, dass das Programm einen Namen bekommen hat, und dass man beim W-Befehl nicht mit den Parametern herumspielt. Tut man Letzteres, kann man sich den Inhalt der Platte zerstören, da der W-Befehl in der Lage ist, jeden beliebigen Sektor auf der Platte ohne den Schutz durch das Betriebssystem zu verändern.

Man kann anschließend das kleine Programm von der DOS-Ebene aus ausführen lassen:

0:10:46:29 C:\>abc
ABCDEFGHIJKLMNOP
0:11:10:41 C:\>


Letztes Upload: 30.03.2017 um 08:35:26