Das nachfolgende Programm kann auf folgende Weise verwendet werden:
- Beim Aufruf des Programms wird die Angabe von zwei Dateinamen erwartet: Quell- und Zieldatei. Im Abschnitt „Namen der Quell- und Zieldatei aus der Kommandozeile extrahieren“ werden die „Handles“ von Quell- und Zieldatei ermittelt. Ein Handle ist die betriebssysteminterne Dateinummer. Das wichtigste über das Konzept der „Handles“ können Sie bei Arbeit mit Dateien (Handle) nachlesen.
- Die Quelldatei wird in den Speicherbereich ab 1000 eingelesen.
- Die Quelldatei wird in den Speicherbereich der Zieldatei (ab 8000) umkopiert, wobei alle vorgefundenen Tabulatoren (ASCII-Zeichen = 09) in Leerzeichen (ASCII-Code=20) umgewandelt werden.
- Der umgewandelte Text wird in die Zieldatei geschrieben.
- Praktischer Tipp
- Weil im nachfolgenden Programm ein Teil des Speichers unbenutzt bleibt (um Platz für zukünftige Erweiterungen zu haben), ist es sinnvoll, den Speicher mit „NOP“-Befehlen („No Operations“) zu füllen. Geben Sie nach dem Start des Debuggers als ersten Befehl f 100 200 90 ein, damit wird ein genügend großer Bereich von 100 bis 200 mit „NOP“-Befehlen (Code: 90 hex) gefüllt.
Namen der Quell- und Zieldatei aus der Kommandozeile extrahieren
Bearbeiten
Wenn man einen Befehl eintippt, speichert das Betriebssystem die Parameter im Programmvorspann ab Adresse 81 und auf Speicherplatz 80 die Bytezahl. Probieren Sie folgendes aus:
- Tippen Sie "debug tab_raus.com q.txt z.txt" ein und drücken Sie Enter
- Tippen Sie den Befehl "d 80" ein. Sie erhalten die folgende Ausschrift:
- 0080 0C 20 71 2E 74 78 74 20-7A 2E 74 78 74 0D 20 71 . q.txt z.txt. q
- Es sind genau 0C grün hervorgehobene Byte, wie es im Byte 80 steht.
- Tippen Sie jetzt den Befehl "a 100" ein und Enter. Der Debugger erwartet jetzt, dass Sie die Befehle eintippen (die blaue Spalte). Mit einem Trick können Sie sich die mühsame, fehlerträchtige Tipperei sparen.
- Markieren Sie in der Tabelle den gesamten blauen Text, nicht mehr und nicht weniger.
- Wechseln Sie in das DOS-Fenster, wo der Debugger auf die Befehlseingabe wartet. Der Cursor blinkt hinter dem Minuszeichen-Prompt.
- Klicken Sie mit der rechten Taste in die blaue Titelleiste (in der Eingabeaufforderung - debug steht).
- Rollen Sie im aufklappenden Menü auf „Bearbeiten“ und klicken Sie auf „Einfügen“. Fertig ist die Eingabe!
- Geben Sie den Befehl "u 100" zur Kontrolle ein (aber eigentlich ist die Kontrolle überflüssig).
- Speichern Sie Ihre Arbeit mit den folgenden drei Befehlen
-n tab_raus.com
|
-r cx
|
: 28
|
-w
|
- Testen Sie diesen Programmabschnitt: Entweder in Einzelschritten mit mehreren Befehlen "t" oder mit "g 127" ohne Anhalten. Sehen Sie sich das Ergebnis mit "d 80" an. Achtung! Das Programm hat noch kein Ende!
IP
|
0100
|
0102
|
0106
|
0108
|
010A
|
010D
|
010F
|
0112
|
0113
|
0114
|
0116
|
0118
|
011A
|
011D
|
011E
|
011F
|
0121
|
0123
|
0125
|
|
Code
|
B500
|
8A0E8000
|
38E9
|
7504
|
B8014C
|
CD21
|
BE8200
|
FC
|
AC
|
3C20
|
75FA
|
B400
|
8864FF
|
56
|
AC
|
3C20
|
75FA
|
B400
|
8864FF
|
|
Befehl
|
MOV |
CH,0
|
MOV |
CL,[80]
|
CMP |
CL,CH
|
JNZ |
10F
|
MOV |
AX,4C01
|
INT |
21
|
MOV |
SI,82
|
CLD |
|
LODSB |
|
CMP |
AL,20
|
JNZ |
0112
|
MOV |
AH,00
|
MOV |
[SI-01],AH
|
PUSH |
SI
|
LODSB |
|
CMP |
AL,20
|
JNZ |
011E
|
MOV |
AH,00
|
MOV |
[SI-01],AH
|
|
Kommentar
|
; CH = 0 setzen
|
; Wieviele Byte wurden übergeben?
|
; Null Byte: Parameter fehlen
|
; nun Zeichenfolge analysieren
|
; Programmaufruf ohne Parameter
|
; Programmende mit ERRORLEVEL = 1
|
; ab Adr. 82 nach 1. SP suchen
|
; Richtung für Stringbefehle
|
; Byte lesen
|
; mit Leerzeichen vergleichen
|
; kein SP, dann zum nächsten Byte
|
; SP durch Null ersetzen
|
;
|
; Beginn 2. Dateiname merken
|
; das zweite Leerzeichen suchen
|
; mit Leerzeichen vergleichen
|
; kein SP, also nächstes Byte
|
; SP durch Null ersetzen
|
|
Im Ergebnis dieses Programmabschnittes endet der Dateiname mit einem Null-Byte, wie es von den DOS-Funktionen "Vorhandene Datei öffnen" und "Neue Datei erstellen" benötigt wird. Der Beginn der zweiten Zeichenkette wurde im Stack abgelegt. Vergleichen Sie (mit dem Befehl "d 80"):
- Vorher: 0080 0C 20 71 2E 74 78 74 20-7A 2E 74 78 74 0D 20 71
- Nachher: 0080 0C 20 71 2E 74 78 74 00-7A 2E 74 78 74 00 20 71
Um diesen Abschnitt zu verstehen, sollten Sie vorher Arbeit mit Dateien (Handle) gelesen haben.
IP |
Code
|
0128 |
BA8200
|
012B |
B000
|
012D |
B43D
|
012F |
CD21
|
0131 |
7305
|
0133 |
B8024C
|
0136 |
CD21
|
0138 |
89C3
|
013A |
BA0010
|
013D |
B90070
|
0140 |
B43F
|
0142 |
CD21
|
0144 |
72ED
|
0146 |
89C1
|
0148 |
EB06
|
|
Befehl
|
MOV |
DX,0082
|
MOV |
AL,00
|
MOV |
AH,3D
|
INT |
21
|
JNB |
0138
|
MOV |
AX,4C02
|
INT |
21
|
MOV |
BX,AX
|
MOV |
DX,1000
|
MOV |
CX,7000
|
MOV |
AH,3F
|
INT |
21
|
JB |
0133
|
MOV |
CX,AX
|
JMP |
0150
|
|
Manuell hinzugefügter Kommentar
|
; AA String mit Dateinamen
|
; Datei zum Lesen öffnen
|
; Handle bestimmen
|
;
|
; CY ist gesetzt, falls Fehler
|
; Dateifehler: Fehlercode im AX
|
; Abbruch mit ERRORLEVEL 2
|
; AX = Handle der Quelle
|
; AA Bereich zum Einlesen
|
; 7000 Byte (von 1000 bis vor 8000)
|
; DOS-Funktion "Datei lesen"
|
;
|
; CY bedeutet: Fehler-Abbruch
|
; AX = gelesene Bytezahl
|
; Bytes von 14A bis 14F ungenutzt
|
|
Speichern vor dem Testen nicht vergessen! Ausführen nur bis vor den Befehl 148 ("g 148"), weil ein Programmende fehlt.
Ab Speicheradresse 1000 muss sich nun die eingelesene Datei q.txt befinden. Kontrollieren Sie mit dem Befehl "d 1000".
Datei durchsuchen und von 1000 nach 8000 kopieren
Bearbeiten
In diesem Programmabschnitt wird der ab Adresse 1000 eingelesene Text Byte für Byte analysiert und in den Speicherbereich ab 8000 umkopiert, wobei Tabulatoren sonderbehandelt werden.
IP |
Code
|
0150 |
BE0010
|
0153 |
BF0080
|
0156 |
AC
|
0157 |
49
|
0158 |
3C09
|
015A |
7502
|
015C |
B020
|
015E |
AA
|
015F |
E31F
|
0161 |
EBF3
|
0163
|
|
Befehl
|
MOV |
SI,1000
|
MOV |
DI,8000
|
LODSB
|
DEC |
CX
|
CMP |
AL,09
|
JNZ |
015E
|
MOV |
AL,20
|
STOSB
|
JCXZ |
0180
|
JMP |
0156
|
|
Manuell hinzugefügter Kommentar
|
; AA Quelle
|
; AA Ziel
|
; Byte von Quelle lesen
|
; Bytezahl -1
|
; ist das ein Tabulator?
|
; kein Tab, Zeichen bleibt also
|
; Tab durch Leerzeichen ersetzen
|
; Byte nach Zieladresse speichern
|
; Ende weil CX=0
|
; nächstes Byte analysieren
|
|
Der Bereich von 0163 bis 017F ist für Erweiterungen vorgesehen und wird zur Zeit nicht gebraucht. Das Programm wird ab 0180 fortgesetzt.
Speicherbereich ab 8000 in Datei schreiben
Bearbeiten
IP |
Code
|
0180 |
5A
|
0181 |
B8003C
|
0184 |
57
|
0185 |
B90000
|
0188 |
CD21
|
018A |
7305
|
018C |
B8024C
|
018F |
CD21
|
0191 |
89C3
|
0193 |
B440
|
0195 |
59
|
0196 |
BA0080
|
0199 |
29D1
|
019B |
CD21
|
019D |
72ED
|
019F |
B8004C
|
01A2 |
CD21
|
01A4
|
|
|
Befehl
|
POP |
DX
|
MOV |
AX,3C00
|
PUSH |
DI
|
MOV |
CX,0000
|
INT |
21
|
JNB |
0191
|
MOV |
AX,4C02
|
INT |
21
|
MOV |
BX,AX
|
MOV |
AH,40
|
POP |
CX
|
MOV |
DX,8000
|
SUB |
CX,DX
|
INT |
21
|
JB |
018C
|
MOV |
AX,4C00
|
INT |
21
|
|
Manuell hinzugefügter Kommentar
|
; AA String mit 2. Dateinamen
|
; Datei zum Schreiben öffnen
|
; EA des überarbeiteten Textes
|
;
|
;
|
; Sprung wenn Datei angelegt wurde
|
; Fehler
|
; Abbruch mit ERRORLEVEL=2
|
; Handle für Datei Schreiben
|
; Schreiben
|
; Endadresse des Zielbereiches
|
; AA Zielbereich
|
; EA - AA = Bytezahl
|
;
|
; Sprung zum Fehlerabbruch, wenn CY
|
; Schreiben fehlerfrei, Programmende
|
;
|
|