|
Dies Programm ist gedacht als Beispielprogramm zur Dateibehandlung mit Handles. Es verwendet den DOS-Interrupt INT 21 mit den Funktionen
- 3c create a file
- 3d open a file
- 3e close a file
- 3f read a file
- 40 write a file
- 41 delete a file
- 42 get file size
- 56 rename a file
Außerdem wird eine i Makro- und Unterprogrammbibliothek namens firm.asm benutzt.
Die Funktionen des Programmes entab gehen aus dem Programmlisting beim Merkmal "get_name3" hervor. Das Merkmal befindet sich etwa in der 30. Zeile der Programmauflistung. Es handelt sich um ein Hilfsprogramm zum Komprimieren und
Expandieren von Textdateien. Die Textdateien lassen sich trotzdem mit Texteditoren weiter anzeigen und bearbeiten.
Dies ist Programm, dessen ausführbare Datei entab.com komprimiert werden sollte. So schrumpft die Größe von entab.com bei Verwendung des Komprimierungprogrammes pklite.exe von 13117 auf 2632 Bytes.
title entab
page 65,120
false equ 0
true equ not false
dump$ equ false ;fuer mdump, rdump
enter$ equ false ;fuer enter, inkjn
intasc$ equ true ;fuer int2asc, asc2int
string$ equ true ;fuer fill, cmpstr, lenstr, instr, movstr, ucaseg, lcaseg
.xlist
include firm.asm
.list
mov si,lparm
;------------------------
;kommandozeile auswerten.
;wenn keine paramter angegeben sind, bedienungsanleitung anzeigen
;und parameter ueber tastatur anfordern.
;
;anschliessend parameter plausibilieren
;------------------------
get_name1:
xor cx,cx
mov cl,b [si] ;laenge der kommandozeile
jcxz get_name3 ;eingabe auf kommandozeile anfordern wenn leer
jmp get_name5
get_name3:
call prmsg
dbl
dbl "Dies Programm entfernt aus einer ASCII-Datei"
dbl "Spaces, indem es Tabulatoren fuer Stelle 8, 16, 24 ... einsetzt."
dbl "Wordstar Steuerzeichen 8Ah/8Dh werden in 0Ah/0Dh gewandelt."
dbl <"In Zeilen mit ' oder ",'"'," werden keine TABs eingesetzt.">
dbl
dbl "-----------------"
dbl "Aufrufe:"
dbl "entab Dateiname im Dialog eingeben"
dbl "entab dateiname Dateiname nicht im Dialog eingeben"
dbl "entab dateiname c entab mit Entfernen von CR * Die anderen Funktionen"
dbl "entab dateiname l entab mit Entfernen von LF * ergaenzen CR-LF wieder"
dbl "entab dateiname u umgekehrte Funktion zu entab Dateiname"
dbl "entab dateiname g entab mit Wandlung in Grossschrift"
dbl "entab dateiname k entab mit Wandlung in Kleinschrift"
dbl <"entab dateiname a auch Zeilen mit ' oder ",'"'," werden komprimiert">
dbl "-----------------"
db 0
get_name4:
inkstr 'Dateiname [u|g|k|a|c|l]: ',40,lparm
mov si,lparm+1
jmp get_name1
get_name5:
getparm ;parameteranfangsadresse nach si
push si
xor cx,cx ;laenge der parameterleiste nach cx
get_name6:
cmp b [si],cr
jz get_name7 ;ende gefunden
inc cx
inc si
jmps get_name6
get_name7:
mov b [si],0 ;ende kennzeichnen
pop si
push si ;stringanfangsadresse
call ucaseg ;wandeln in grossschrift
pop si
push si ;stringanfangsadresse
get_name8:
cmp b [si],spc ;suchen ob Space enthalten
jz get_name9 ;ja
inc si
loop get_name8
get_name9:
cmp b [si],spc ;Space gefunden ?
mov b untab,'E' ;kein Space, Parameter E unterstellen
jne get_name12
mov b [si],0 ;zwischenstring kennzeichnen
inc si
mov al, b [si]
mov b untab,al
get_name12:
pop si ;anfangsadresse parameter (dateiname)
mov di,offset q_datei
call movstr ;dateiname (quelle) uebernehmen
mov di,offset q_datei + 1
cmp b [di],':'
je get_name13
jmp get_name15
get_name13:
call prmsg
dbl 'Das Programm arbeitet mit RENAME. Deshalb ist die Angabe'
dbl 'des Laufwerkes nicht zulaessig.'
dbl 'Bitte ggf. auf das Verzeichnis setzen und entab erneut starten!'
db 0
jmp get_name3
;---------------------
;plausibilierung des komprimierungsparamters
;---------------------
get_name15:
mov di, offset kompr ;zugelassene komprimierunggsarten
mov si, offset untab
call instr ;zero flag gesetzt wenn nicht enthalten
jnz verarb
prstr "nur E, U, G, K, A, C, L oder kein Parameter zugelassen!"
jmp get_name3
;---------------------
;dateien eroeffnen
;---------------------
verarb:
fopen q_datei,0 ;nur lesen
jmpc err1
mov handle1,ax ;dateihandle speichern
fcrat z_datei,0 ;create zieldatei (schreiben)
jmpc err2
mov handle2,ax
;---------------------
;quelldatei zeilenweise lesen und verarbeiten
;---------------------
lese:
call line_input ;get a line
mov dx,lin_buf
mov cx,bx ;zeilenlaenge nach cx
mov si,offset in_buf
add si,cx
or cl,ch ;leerzeile?
jz lese3 ;ja
lesecut: ;trailing spaces entfernen
dec si
cmp b [si],spc
jne lesecut9
loop lesecut
lesecut9:
inc si
lese3:
mov b [si],0 ;stringende einsetzen
push cx ;zeilenlaenge
mov si,offset in_buf
pop cx ;zeilenlaenge
or cx,cx
jz lese5 ;keine ausgabe der zeile wenn leerzeile
;---------------------
;zeile verarbeiten, z.b. komprimieren und gross/kleinschriftwandlung
; und zur zieldatei ausgeben. cr/lf wird getrennt ausgegeben
;---------------------
push cx
mov w lin_buf_bel,cx ;tatsaechliche zeilenlaenge speichern
call verarbeite ;verarbeitung der zeile
pop cx ;zeilenlaenge
jmps lese7
lese5:
cmp eof_B_BUF,'Y' ;war EOF?
je lese7 ;ja - keine ausgabe cr lf bei leerer letzter zeile
lese6:
mov al,b untab ;lf nur ausgeben, wenn nicht L
cmp al,'L' ;als Partameter angegeben
jne lese62
fwrit handle2,cr_buf,1 ;Ausgabe nur cr
jmpc err4
jmps lese7
lese62:
cmp al,'C' ;cr nur ausgeben, wenn nicht C
jne lese65 ;als Parameter angegebn
fwrit handle2,cr_buf+1,1
jmpc err4
jmps lese7
lese65:
fwrit handle2,cr_buf,2 ;ausgabe cr lf
jmpc err4
lese7:
cmp eof_B_BUF,'Y' ;war EOF?
je lese8
jmp lese
;---------------------
;wenn eof: dateigroessen anzeigen zum vergleich
;und dateien loeschen/renamen, dass die komprmierte / bearbeitete datei
;uebrig bleibt.
;---------------------
lese8:
xor dx,dx ;Dateigroesse "vorher" anzeigen
xor cx,cx
mov al,2
mov bx,handle1
int21 42h
mov di,offset ziff1
call int2asc
call prmsg
db 'Dateilaenge vorher (Bytes): '
ziff1 db spc,cr,0
xor dx,dx ;Dateigroesse "nachher" anzeigen
xor cx,cx
mov al,2
mov bx,handle2
int21 42h
mov di,offset ziff2
call int2asc
call prmsg
db 'Dateilaenge nachher (Bytes): '
ziff2 db spc,cr,0
call end_file
;loeschen alte datei
lea dx,q_datei
int21 41h
jmpc err7
;rename arbeitsdatei in alte datei
lea di,q_datei ;neuer name
push ds
pop es
lea dx,z_datei
int21 56h
jmpc err8
jmp ret0
;---------------------
;unterprogrammsammelsurium
;---------------------
;upro verarbeitung und ausgabe der zeile in in_buf, laenge wie cx
;---------------------
verarbeite:
mov al,b untab ;zeile expandiert ausgeben
cmp al,'U'
jne verarb2
verarb1:
mov si,offset in_buf
add si,cx
mov b [si],cr ;cr lf ergaenzen
inc si
mov b [si],lf
inc cx
inc cx
fwrit handle2,in_buf,cx
jmpc err4
ret
verarb2: ;bei allen anderen formen zeile komprimieren
cmp al,'A'
je verarb11 ;bei a jede zeile komprimieren
mov si,offset in_buf
push cx
mov dh,'"'
mov dl,"'"
verarb4:
mov al,b [si] ;bei nicht A nur zeilen komprimieren,
cmp al,dh ;die nicht ' und " enthalten
je verarb6
cmp al,dl
je verarb6
inc si
loop verarb4
jmps verarb10 ;zum komprimieren
verarb6:
pop cx
jmps verarb1 ;satz aus in_buf heraus schreiben
verarb10:
pop cx
verarb11:
call entab ;komprimieren hier...
mov si,offset out_buf
mov al,b untab
cmp al,'K' ;Wandlung in Kleinschrift
jne verarb18
call lcaseg
jmps verarb20
verarb18:
cmp al,'G' ;Wandlung in Grossschrift
jne verarb20
call ucaseg
verarb20:
mov cx,w lout_buf_bel
mov si,offset out_buf
add si,cx
mov al,b untab ;cr nur ergaenzen, wenn nicht C
cmp al,'C' ;als Parameter angegeben
je verarb21
mov b [si],cr ;cr ergaenzen
inc si
inc cx
verarb21: ;lf nur ergaenzen, wenn nicht L
cmp al,'L' ;als Parameter angegenem
je verarb22
mov b [si],lf
inc si
inc cx
verarb22:
fwrit handle2,out_buf,cx
jmpc err4
ret
;------------------
;komprimieren durch tabulatoren
;------------------
entab:
xor cx,cx
entab10:
add cx,8
mov dx,8 ;teilstringlaenge
mov ax,w lin_buf_bel
cmp ax,cx
jnb entab20 ;sprung, wenn erhoehung der adresszeigers cx
jz entab20 ;noch ging
sub cx,8
mov dx,w lin_buf_bel
sub dx,cx ;dx: rest der stringlaenge
mov cx,w lin_buf_bel
entab20:
mov si,offset in_buf
add si,cx
push cx
mov cx,dx ;max dx-mal (8 oder teilstringlaenge)
dec si ;rechter rand der teilkette
entab30:
cmp byte ptr [si],spc
jne entab40
mov byte ptr [si],9
dec si
loop entab30
entab40:
pop cx
mov ax,w lin_buf_bel
cmp ax,cx
jnz entab10
;kopieren quellstring nach zielstring
mov si,offset in_buf
mov di,offset out_buf
xor bx,bx
mov cx,w lin_buf_bel
entab50:
mov al,byte ptr [si]
cmp al,9
je entab60
entab55:
mov byte ptr [di],al
inc di
inc si
inc bx
loop entab50
entab99:
mov dx,di
mov di,offset out_buf
sub dx,di
mov w lout_buf_bel,dx
ret
entab60:
mov ax,bx ;position 7 des teilstrings?
and al,7
cmp al,7 ;dann wird der tab ein space
jne entab65
mov al,spc
jmp entab55
entab65: ;tab zum zielstring und vorlesen auf anfang
mov byte ptr[di],tab ;naechster teilstring
inc di
jmp entab75
jz entab99 ;zur sicherheit
entab70:
inc si
inc bx
mov ax,bx
and al,7
jz entab50
entab75:
loop entab70
jmp entab99 ;zur sicherheit
;---------------------
;upro dateien schliessen
;---------------------
end_file:
fclose handle1
jmpc err5
fclose handle2
jmpc err6
ret
;---------------------
;fehlermeldungen fuer dateibehandlung
;---------------------
ERR1: prstr 'Quell'
jmps err1_2
ERR2: prstr 'Ziel'
ERR1_2: prstr 'datei laesst sich nicht oeffen'
jmp ret1
ERR3: prstr 'Lesefehler!'
jmp ret1
ERR4: prstr 'Schreibfehler!'
jmp ret1
ERR5: prstr 'Quell'
jmps err5_6
ERR6: prstr 'Ziel'
ERR5_6: prstr 'datei laesst sich nicht schliessen'
jmp ret1
ERR7: prstr 'Quelldatei laesst sich nicht loeschen'
jmp ret1
err8: call prmsg
dbl 'Rename der Arbeitsdatei in Quelldatei nicht moeglich.'
dbl 'Die Arbeitsdatei heisst jetzt ENTAB.WRK'
dbl 'Sie enthaelt die fertig bearbeiteten Daten.'
db 0
jmp ret1
;---------------------
;upro lese eine zeile nach in_buf. dabei werden tabs aufgeloest
;---------------------
line_input:
mov cx,lin_buf
xor bx,bx ;zeichenzaehler
mov si,offset in_buf
line_input1:
pushreg
call getbyte ;hole 1 byte
popreg
cmp eof_B_BUF,'N' ;EOF?
jne line_input99 ;ja
cmp al,8dh ;wordstar cr ?
je line_input9
cmp al,8ah ;wordstar lf ?
je line_input9
line_input2:
cmp al,cr ;cr?
je line_input99 ;ja
cmp al,lf ;lf unter Umstaenden ueberlesen
je line_input8
cmp al,tab
je line_input5
mov b [si],al
inc bx
inc si
line_input3:
mov lezei,spc ;merke space als letztes zeichen
loop line_input1
line_input4:
prstr 'Abbruch- Zeile zu lang'
call end_file
jmp ret1
line_input5: ;tabulatoren aufloesen
mov b [si],spc
inc bx
inc si
mov ax,bx
and ax,7h ;tabulatorposition erreicht ?
jz line_input3 ;ja
loop line_input5 ;nein
jmps line_input4 ;bei ueberlauf
line_input8: ;lf wurde gelesen
cmp lezei,cr ;ueberlesen, wenn letztes zeichen cr war
jne line_input99 ;sonst wie cr behandeln
mov lezei,al
jmps line_input1
line_input9:
and al,7fh ;wordstar cr/lf wird normales cr/lf
jmps line_input2
line_input99:
mov lezei,al ;merke letztes zeichen
ret
;---------------------
;upro lese 1 byte aus der quelldatei nach al
;---------------------
getbyte:
mov bx,anz_b_buf ;noch was im puffer?
or bx,bx
jz getbyte10 ;nein
getbyte5:
mov bx,pos_b_buf ;1 Byte aus Puffer abholen
lea si,b_buf
mov al,[si][bx]
inc bx
mov pos_b_buf,bx
dec anz_b_buf
ret
getbyte10:
cmp eof_B_BUF,'Y' ;war EOF?
je getbyte99 ;ja
push cx
fread handle1,b_buf,lb_buf
pop cx
mov anz_b_buf,ax ;anzahl gelesener bytes
jmpc err3
mov pos_b_buf,0 ;position 0
or al,ah ;eof?
jnz getbyte5 ;nein
mov eof_B_BUF,'Y'
getbyte99:
mov al,1ah ;ja, dann eof melden
ret
;---------------------
;datenbereiche
;---------------------
q_datei db 40 dup(32)
z_datei db 'ENTAB.WRK',0
handle1 dw ?
handle2 dw ?
untab: db 0 ;komprimerungsart
db 0 ;0 kennzeichnet stringende komprimierungsart
kompr: db 'EUGKACL',0 ;zugelassene komprimierungsarten
cr_buf: db cr,lf ;zeilewechsel
pos_b_buf dw 0 ;pufferposition
anz_b_buf dw 0 ;bytes im puffer
eof_B_BUF db 'N' ;kein EOF
lezei db 0 ;letztes gelesenes zeichen
b_buf: db 1024*8 dup (0)
lb_buf equ $-b_buf
in_buf: db 1024 dup (0)
lin_buf equ $-in_buf
lin_buf_bel: dw 0 ;wie weit in_buf wirklich belegt ist
out_buf: db 1024 dup (0)
lout_buf equ $-in_buf
lout_buf_bel: dw 0 ;wie weit out_buf wirklich belegt ist
code ends
end start
|