Maschinensprache i8086/ Filter/ 09-SP-V1

Aus Wikibooks

Übersicht[Bearbeiten]

Das nachfolgende Programm kann auf folgende Weise verwendet werden:

  1. 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.
  2. Die Quelldatei wird in den Speicherbereich ab 1000 eingelesen.
  3. 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.
  4. 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

Quelldatei öffnen und einlesen[Bearbeiten]

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
;