Dies für den Assembler ML 6.14 geschriebene Quellprogramm ist ein Beispielprogramm zur Dateibehandlung mit Handles. Es verwendet Handles für Lesen von Standardeingabe und zum Schreiben zur Standardausgabe. In eine zweiten Version des
gleichen Programmes wird die Verwendung der Funktion 71h mit Unterfunktion 6ch zur Verarbeitung von Dateien mit langen Dateinamen demonstriert.
Die dritte Version zeigt ein vergleichbares Quellprogramm in der Programmiersprache C. Der Quellprogrammcode ist erheblicher kürzer als die beiden Assemblervarianten. Die Übersetzung des C-Proramms erfolgte mit Hilfe der Open-Source-IDE von →Code::Blocks. IDE steht für Integrated Development Environment (Integrierte Entwicklungsumgebung). Diese Variante funktioniert auch unter Windows 10.
Verwendete Funktionen des Interrupts 21h:
- 3c create a file
- 3d open a file
- 3e close a file
- 3f read a file
- 40 write a file
- 42 get file size
- 5b create new file
- 716ch create / open file (supports long file names)
Es sei der Hinweis auf die hier nicht verwendete Funktion 6C des INT 21H hingewiesen: Sie fasst die Funktionen 3C, 3d und 5B zusammen.
Außerdem wird eine Makro- und Unterprogrammbibliothek namens firm.mac benutzt.
Da die Verwendung der Handles zum Lesen von Standardeingabe und zum Schreiben zur Standardausgabe in veröffentlichten Programmbeispielen kaum vorkommt, wird vorher das spezielle Testprogramm KOPIE gezeigt.
KOPIE - das Programm für den Vorversuch
Das kleine Programm KOPIE kopiert von der Standardeingabe zur Standardausgabe. Die Standardeingabe wird über den Handle 0 angesprochen. Die Standardausgabe wird über den Handle 1 angesprochen.
Unter MS-DOS sind fünf Handles standardmäßig für Geräte vorbelegt:
- Handle 0 ist das Standardeingabegerät CON. Es verweist normalerweise auf die Tastatur
- Handle 1 ist das Standardausgabegerät CON. Es verweist normalerweise auf den Bildschirm.
- Handle 2 ist das Standardgerät zur Fehlerausgabe CON. Es verweist normalerweise auf den Bildschirm.
- Handle 3 ist verweist auf die serielle Standardschnittstelle (AUX).
- Handle 4 verweist auf den Standarddruckeranschluss (PRN).
Um das Öffnen und Schließen von Tastatur und Bildschirm braucht sich das Programm nicht zu bekümmern.
Tastatur und Bildschirm lassen sich durch Dateien ersetzen. Dazu dienen die Umleitungssymbole
< für Eingabe (statt Tastatur aus Datei )
> für Ausgabe in eine neue Datei (statt Bildschirm in Datei). Ist die Datei bereits vorhanden, so wird sie vorher gelöscht.
>> für Ausgabe zur Erweiterung einer bereits bestehenden Datei. Falls die Datei nicht vorhanden war, wird sie neu angelegt.
Nach Eingabe der Befehlszeile
kopie <hallo1.txt >hallo2.txt
wird die Datei HALLO1.TXT in die Datei HALLO2.TXT kopiert.
Das Quellprogramm ist überraschend einfach. Am Anfang des Quellprogrammtextes sind einige Anregungen für Versuche aufgeführt.
.MODEL TINY
;======================================
;Zeigt, wie einfach sich ein Kopierprogramm mittels Handles
;programmieren laesst
;Beim Eintippen von Text das Programm mit ctrl C anfordern!
;Vorher die letzte Eingabezeile mit der Enter-Taste abschliessen!
;---
; Zum Testen nacheinander aufrufen mit
; kopie Eingetippter Text sollte auf dem Bildschirem erscheinen
; kopie >hallo.txt Eingetippter Text kopieren in die Datei hallo.txt
; kopie <hallo.txt >hallo1.txt Die Datei hallo.txt soll in die Datei
; hallo1.txt kopiert werden
; kopie <hallo.txt >>hallo1.txt Die Datei hallo.txt sollte an die Datei
; hallo1.txt angehängt werden
;======================================
;
FALSE EQU 0
TRUE EQU NOT FALSE
dump$ equ false ;fuer mdump, rdump
prompt$ equ false ;fuer PROMPT, INKJN
intasc$ equ false ;fuer INT2ASC, ASC2INT
string$ equ false ;fuer CMPSTR, LENSTR, INSTR, MOVSTR
.CODE
ORG 100h
kopie: JMP around
include firm.mac
;Text, gleichzeitig Puffer
Text DB '0'
;
around:
mov bx,0 ;Handle console (eingabe)
mov cx,1 ;1 Zeichen lesen
mov dx,offset Text
mov ah,3fh ;lesen
int 21h
or ah,al ;ax ist 0 wenn EOF
jz fertig
mov bx,1 ;Handle console (ausgabe)
mov cx,1 ;Länge des Textes
mov dx,offset Text
mov ah,40h ;schreiben
int 21h
jmp around
fertig:
MOV AX,4C00h ;EXIT
INT 21h
END kopie
Von KOPIE nach TEE
Unter Unix (wie Linux) und bei der alternativen Kommandooberfläche 4DOS für MS-DOS bewirkt der Befehl „TEE” eine Kopie der Bildschirmausgabe eines Programmes in eine Datei. Voraussetzung ist, dass dies Programm seine Bildschirmausgaben
über die Standardausgabe Handle 1 durchführt. Etliche der von Microsoft bei MS-DOS mitgelieferten Programme und Kommandos erfüllen diese Voraussetzung.
Beispielsweise zeigt dir | tee zwi.txt die Inhaltsanzeige des Verzeichnisses auf dem Bildschirm und erzeugt eine Kopie der Bildschirmausgabe in der Datei ZWI.TXT.
TEE lässt sich gut zur Dokumentation der mit HELP anzeigbaren Hilfstexte verwenden. Beispielsweise steht nach Eingabe von
help|tee help.txt
Das MS-DOS Kommandoverzeichnis in der Datei HELP.TXT.
Nach Eingabe von help cd|tee help_cd.txt
enthält HELP_CD.TXT den Hilfstext für das Kommando CD (Change Directory).
Bei VISTA in sieht die solcherart erzeugte Datei HELP_CD.txt so aus:
Wechselt das Verzeichnis oder zeigt dessen Namen an.
CHDIR [/D] [Laufwerk:][Pfad]
CHDIR [..]
CD [/D] [Laufwerk:][Pfad]
CD [..]
.. Gibt an, dass Sie in das übergeordnete Verzeichnis wechseln möchte.
Geben Sie "CD Laufwerk:" ein, um das aktuelle Verzeichnis auf dem angegebenen
Laufwerk anzuzeigen. Mit CD ohne Parameter wird das aktuelle Laufwerk und
Verzeichnis angezeigt.
Verwenden Sie die /D-Option, um zusätzlich zum Wechseln des Verzeichnisses
auch das aktuelle Laufwerk zu wechseln.
Wenn die Befehlserweiterungen aktiviert sind, wird CHDIR folgendermaßen
verändert:
Der angegebene Verzeichnisname wird so konvertiert, dass dieser bezüglich
Groß- und Kleinschreibung dem Namen auf dem Laufwerk entspricht. So wird durch
CD C:\TEMP der aktuelle Pfad auf das Verzeichnis C:\Temp festgelegt, wenn ein
Verzeichnis mit diesem Namen auf dem Laufwerk existiert.
Der CHDIR-Befehl behandelt Leerzeichen nicht als Begrenzungszeichen, so dass es
möglich ist, in ein Unterverzeichnis zu wechseln, dessen Name Leerzeichen
enthält, ohne diese mit Anführungszeichen einzuschließen. Beispiel:
cd Eigene Dateien
ist dasselbe wie:
cd "Eigene Dateien"
Wenn die Befehlserweiterungen nicht aktiviert sind, müssen die Anführungs-
zeichen angegeben werden.
Die Funktionen des ausführbaren Programmes TEE gehen aus dem Programmlisting bei der Hilfstextanzeige hervor. Die Hilfstextanzeige befindet sich beim Merkmal „helpanzeige” der Programmauflistung.
Das Programm stellt die Hilfsanzeige mit dem Aufruf TEE /? auf dem Bildschirm dar. Diese Ausgabe erfolgt nicht über ein Handle. Die Hilfszeige von TEE lässt sich somit nicht in eine Datei umleiten!
.MODEL TINY
comment #
======================================
Uebertraegt Daten von der Standardeingabe zur Standardausgabe. Zusaetzlich
wird eine Kopie der Daten in die angegebenen Zieldatei geschrieben.
Wenn der Schalter /A angegeben ist, wird die Zieldatei erweitert.
Ist kein Schalter /A angeben, wird die Zieldatei neu angelegt.
Ist bei Angabe des Schalters /A keine solche Zieldate vorhanden, wird
die Zieldatei neu angelegt.
Die Ausgabe in eine Zieldatei entfaellt, wenn keine Zieldatei
angegeben ist.
Ctrl Z (hexdezimal 1A) von der Standardeingabe bewirkt ein Programmende.
======================================
#
FALSE EQU 0
TRUE EQU NOT FALSE
dump$ equ true ;fuer mdump, rdump
prompt$ equ false ;fuer PROMPT, INKJN
intasc$ equ false ;fuer INT2ASC, ASC2INT
string$ equ false ;fuer CMPSTR, LENSTR, INSTR, MOVSTR
.CODE
ORG 100h
_start: JMP around
include firm.mac
;---------------------
;datenbereich
;---------------------
zdatei db 40h dup(32)
handle dw ?
text DB '0' ;text, gleichzeitig Puffer
append db 0 ;kennzeichen Append, Enthaelt A wenn der
;Parameter /A bzw, /a eingetippt wurde.
;Enthaelt E, wenn Dateiname ohnme /A bzw. /a
;angegeben ist.
;---------------------
;Unterprogramme
;---------------------
;upro Zieldatei schliessen
;---------------------
end_file:
fclose handle
jmpc err6
ret
;---------------------
; upro Zieldatei kreeiren und öffnen
; Funktion 3ch oder 5bh steht bereits vor Unterprogrammaufruf in ax
;---------------------
create_file:
mov dx,offset zdatei
mov cx,0h ;normale Datei
int21
jc create_file5
mov handle,ax
ret
create_file5:
cmp ax,50h ;Datei bereits existent ?
jne err2 ;nein, anderer Fehler
fopen zdatei,1 ;ja, dann normales oeffnen zum Schreiben
jc err2
mov handle,ax
mov ah,42h ;und auf Dateiende positionieren
xor dx,dx
xor cx,cx
mov al,2
mov bx,handle
int dos
jc err5
ret
;---------------------
;fehlermeldungen fuer dateibehandlung
;---------------------
ERR1: prstr 'Quell'
jmps err1_2
ERR2: prstr 'Ziel'
ERR1_2: prstr 'datei laesst sich nicht oeffnen'
jmp ret1
ERR4: prstr 'Schreibfehler!'
jmp ret1
ERR5: prstr 'Positionierung auf Dateiende nicht erfolgreich!'
jmp ret1
ERR6: prstr 'Ziel'
ERR5_6: prstr 'datei laesst sich nicht schliessen'
jmp ret1
ERR7: prstr 'Quelldatei laesst sich nicht loeschen'
jmp ret1
;---------------------
;Hauptprogramm
;---------------------
;Verarbeiten der Eingabeparameter. Im PSP sind nur die Eingabeparameter
;enthalten, die nicht mit einem Pipe-Symbol (<>|) beginnen.
;-----
; 1. Schritt: ob /? als einziger Parameter eingetippt wurde. Dann
; erfolgt Anzeige des Hilstextes und sofortige Programmende
;-----
around:
cmp b cs:lparm,03h
jne para2
cmp b cs:lparm+2,"/" ;/? bewirkt Hilfstextanzeige
jne para2
cmp b cs:lparm+3,"?"
jne para2
helpanzeige:
call prmsg
dbl "Dupliziert die Standardausgabe in eine benannte Datei."
dbl "Aufruf: tee [zieldateiname [/A]]"
dbl "Bei Angabe von /A wird die Datei erweitert (append)."
dbl "Die Ausgabe in eine benannte Datei entfaellt, wenn kein"
dbl "Zieldateiname angegeben wurde."
db cr
dbl "Bei Tastatureingabe: Ctrl Z bewirkt Programmende."
db 0
jmp fertig
;-----
; 2. Schritt: ist /a oder /A enthalten? Wenn ja, wird das Kennzeichen
; Append für Dateierweiterung gesetzt.
;-----
para2: cmp b cs:lparm,00h
jne para3
jmp lesen ;es wurden gar keine Parameter eingegeben
para3: mov si,lparm ;Vergleichsvorbereitung: Parameterlaenge
xor ch,ch ;nach si
mov cl,[si]
para5: inc si ;Adresszeiger
cmp b [si],'/' ;suchen Bruchstrich
je para6 ;Bruchstrich gefunden
loop para5
jmp get_name ;kein Bruchstrich enthalten
para6: inc si ;a oder A nach Bruchstrich?
mov al,b [si]
and al,0dfh ;Kleinschrift in Grossschrift
cmp al,"A"
jne get_name ;es war nicht /a oder /A
mov append,al ;Kennzeichen Append setzen
dec si ;im Eingabestring des PSPs den /
mov b [si],cr ;mit cr ueberschreiben
;-----
; 3. Schritt Aufbereiten des Dateinamens und Einspeichern des Namens
; in Bereich zdatei
; Der Fall Parameterlaenge=0 wurde bereits beim Label para2 behandelt.
;-----
get_name:
mov si,lparm ;Parameterlaenge nach cx
xor ch,ch
mov cl,[si]
getparm ;Parameteranfangsadresse nach si
mov di,offset zdatei
get_name6:
mov al,b [si]
cmp al,cr ;Absuchen des Parameterbereichs auf cr
jz get_name7 ;Ende gefunden
mov b [di],al ;1 Byte vom Dateinamen nach zdatei
inc di
inc si
jmps get_name6
get_name7:
mov b [di], 00h ;Ende kennzeichnen
mov si, offset zdatei
;-----
;get_name8 wird durchlaufen, wenn ein Zieldateiname angegeben wurde
;-----
get_name8:
cmp append,"A" ;war /A angegeben?
mov ah,5bh ;fuer create new file
je get_name9 ;ja
mov append,"N" ;append war nicht angegeben
mov ah,3ch ;fuer create file ggf. loeschen einer
;vorhanden Datei gleichen Namens
;-----
;Erzeugen der Zieldatei
;-----
get_name9:
call create_file
comment #
Bis zum Kommentarende steht eine nicht mehr benoetigte Testhilfe wegen
Problemen mit den Original-Tastaturtreiber bei VISTA's CMD.EXE
;Anlesen der Standardeingabe. Falls das erste Zeichen EOF ist, wird EOF ignoriert.
;
mov bx,0 ;Handle console (eingabe)
mov cx,1 ;1 Zeichen lesen
mov dx,offset text
mov ah,3fh ;lesen Standardeingabe
int 21h
jc mist
or ah,al ;ax ist 0 wenn EOF
jnz mist3
jmp mist2
mist: prstr "CY beim Anlesen der Standardeingabe gesetzt"
jmp fertig
mist2: prstr "CY nicht gesetzt, ax=0000"
jmp fertig
mist3: pusha
rdump
popa
mdump offset handle,4
prstr "CY nicht gesetzt, ax nicht 0000"
jmp lesen2
#
lesen:
mov bx,0 ;Handle console (eingabe)
mov cx,1 ;1 Zeichen lesen
mov dx,offset text
mov ah,3fh ;lesen Standardeingabe
int 21h
or ah,al ;ax ist 0 wenn EOF
jnz lesen2
jmp fertig
lesen2:
mov al,text
cmp al,01ah ;ctrl z bewirkt Programmende
je fertig
mov bx,1 ;Handle console (ausgabe)
mov cx,1 ;Länge des Textes
mov dx,offset Text
mov ah,40h ;schreiben Standardausgabe
int 21h
cmp append,0
jz lesen ;wenn ohne Zieldatei
fwrit handle,text,1 ;schreiben in Zieldatei
jnc lesen
; or ax,3030h ;wenn Schreibfehler
; push ax ;alte Testhilfe. Zeigt den Inhalt von
; mov al,ah ;AX auf dem Bildschirm an
; call printchr
; pop ax
; call printchr
jmp err4
fertig:
cmp append,0
jz fertig1
call end_file ;Zieldatei schliessen (falls geoeffnet wurde)
fertig1:
jmp ret0
END _start
|