masm
COMMENT ` (haftmann#software) +++FREEWARE+++
WRSTR Ausgabe nullterminierter String
WRSTRLN Ausgabe nullterminierter String mit NewLine
_ZKOLF fr WrStrLn erforderlich...
SKEND Stringende nullterminierter Strings DS:SI suchen, KEIN Unterprogramm!
_GETENV PE: DS:SI ASCIIZ ([meist] Grobuchstaben!!) ohne '=', DS auf PSP-Seg.
PA: ES:DI ASCIIZ oder CY=1: Nicht gefunden
VR: AX,ES,DI
_PARAM0 PA: ES:DI ASCIIZ ParamStr(0) - eigener Dateiname
_SEEKNAME PE: DS:SI: ASCIIZ [Pfad\]Dateiname
PA: DS:SI: Zeigt auf Dateiname allein
_SEEKEXT PE: DS:SI: ASCIIZ [Pfad\]Dateiname
PA: DS:SI: Zeigt auf Extension ab dem Punkt
_PATHCOPY PE: DS:SI: ASCIIZ [Pfad\]Dateiname
ES:DI: Puffer fr ASCIIZ Pfad (80 Bytes o..)
PA: DS:SI: zeigt auf Dateiname allein
ES:DI: zeigt auf Byte nach der Null im Puffer
_ISNAMECHAR Testet AL auf gltiges Zeichen fr Dateiname, '.' eingeschlossen
_GLOBBING Vergleicht Maske DS:SI mit Dateiname ES:DI; CY=1: unpassend
(UNIX-Globbing!) VR: AX
_SEEKINPATH PE: DS:SI Dateiname
ES:DI Puffer ca.128 Zeichen
PA: Gefllter Puffer; CY=1: Nicht gefunden
- Enthlt der Dateiname bereits einen Pfad, wird nur StrCpy ausgefhrt
- Zuerst wird das aktuelle Vrz. durchsucht
- Ist nur ein Laufwerk angegeben, wird ebenfalls der Pfad abgesucht
- Wurde keine Extension angegeben, wird .COM und .EXE angenommen;
niemals .BAT!
- Eine leere Extension wird erzwungen durch nachgestellten Punkt
- Die Umgebungsvariable, nach der gesucht wird, lautet PATH
HINWEIS: Es erfolgt FindFirst! DTA lokal im Stack!
(Gesicherte Funktion unter Novell Netware mit Executables,
die nicht lesbar sind! Geschwindigkeitsgewinn bei residentem DIET.)
_FEXPAND PE: DS:SI: unvollst. Dateiname, ES:DI: Puffer fr vollst. Dateiname
PA: SI unverndert, DI zeigt hinter die Null im Puffer
VR: AX,DI +++ Puffer drfen sich NICHT berlappen! +++
Hinweis: Es erfolgt KEIN TEST des angegebenen "Dateinamens" auf Gl-
tigkeit oder Vorhandensein, nur CurDrv und CurPath wird davorgesetzt!
_ZKOUT Ausgabe nullterminierter String auf StdOut, PE: DS:SI, VR: AL,F
Zieht ZKOUT2 nach sich!
_ZKOUT2 Ausgabe nullterminierter String auf StdOut, PE: DS:DX, VR: AL,F
Innerhalb von ZKOUT2 definiert: ZKOUTH Ausgabe nullterminierter
String auf Handle-File, PE: DS:DX, BX=Handle (offen!) VR: AL,F
_STRCPY StringCopy normal ds:si->es:di
_STRCPR StringCopy revers es:di->ds:si fr Environmentvariablen
_STRCPX StringCopy bis Weiraum ds:si->es:di, zieht _CHKWS nach sich
Bei allen StringCopy-Aktionen: PA: SI,DI zeigen HINTER die Null
VR: SI,DI,AL,F
_STRCMP StringCopmare case-sensitiv
_STRICMP StringCompare case-insensitiv
_INSTR Stringsuche case-sensitiv
ES:DI Langer String, DS:SI Kurzer String, PA: BX: Position
_INSTRI Stringsuche case-insensitiv
_YESNO Gibt '? [Y/N] ' auf Bildschirm aus und wartet auf genau diese beiden
Tasten. Anschlieend Ausgabe des geupcasten Zeichens und CRLF
Zieht _CRLF nach sich!
_JANEIN Dito in deutsch
_INLIN Primitive Zeileneingabe mit Ausgabe nullterminierter String
PE: ES:DI=Puffer, CX: Puffergre VR:AX; InSec definiert
echolose Eingabe fr Pawrter
_ERRMG DOS-Nummer-Fehlermeldungen deutsch, AL=Fehler-Nummer
`
ideal
macro SKEND ;;Suche Stringende von DS:SI
local sk1
sk1: lodsb
or al,al
jnz sk1
endm
macro WRSTR w1 ;;Write nullterminierter String
mov dx,ofs w1
call zkout2
endm
macro WRSTRLN w1 ;;Write nullterminierter String mit NewLine
mov dx,ofs w1
call zkonl
endm
macro _ZKONL ;;Ausgabe ASCIIZ (DX) mit anschlieendem CRLF
;;zieht CRLF aus PROLOG und ZKOUT2 nach sich!
zkonl: call zkout2
_CRLF
_ZKOUT2
endm
macro _GETENV ;GetEnvVar(PChar):PChar, CY=1: Fehler
;Voraussetzung: ENV existiert!
proc getenv
mov es,[2ch]
xor di,di
xor ax,ax
cld
jr @@f
@@l:
push si
@@1: lodsb
; call UpCase ;tja, richtig oder falsch?
or al,al
jz @@2
scasb
jz @@1
pop si
jr @@3
@@2:
mov al,'='
scasb
pop si
je @@e ;gleich
@@3: ;ungleich
dec di
mov al,ah ;AL=0
@@4: scasb
jnz @@4
jr @@l
@@f: ;Fugesteuerte While-Schleife
cmp [by es:di],1 ;Ende Env?
jnc @@l
@@e: ret
endp
endm
macro _PARAM0 ;ParamStr(0) ermitteln, CY=1: Fehler
proc param0
mov es,[2ch]
xor ax,ax
cld
jr @@2 ;falls ENV leer! - knnt ja sein...
@@1: scasb
jnz @@1
@@2: scasb
jnz @@1
inc ax ;ax=1
scasw
ret
endp
endm
macro _ISNAMECHAR
proc IsNameChar
call UpCase
cmp al,'!'
jc @@e
cmp al,''''
cmc
jnc @@e
cmp al,'-'
jz @@e
cmp al,'.'
jz @@e
cmp al,'0'
jc @@e
cmp al,':'
cmc
jnc @@e
cmp al,'@'
jc @@e
cmp al,'['
cmc
jnc @@e
cmp al,80h
@@e: ret
endp
endm
macro _GLOBBING ;DS:SI=Maske, ES:DI=Name
proc Globbing
cld
@@r: push si di
@@l: lodsb ;Maske
mov ah,[es:di] ;Name
or al,al
jnz @@1
cmp al,ah ;Auch Null? CY=1 wenn ah<>0! (Stringenden
; fallen nicht zusammen!)
jr @@e ;okay oder auch nicht!
@@1:
cmp al,'*'
jnz @@2
@@3: call @@r ;rekursiv!
jnc @@e
xor al,al
scasb
jc @@3
jr @@f ;Fehler
@@2:
inc di
or ah,ah
jz @@f
cmp al,'?'
jz @@l
call UpCase
xchg ah,al
call UpCase
cmp al,ah
jz @@l
@@f: stc
@@e: pop di si
ret
endp
endm
macro _SEEKNAME ;Sucht Dateinamen selbst im kompletten Pfad (DS:SI)
proc SeekName
cld
push dx
mov dx,si ;merken
SKEND ;Ende suchen
jr @@f
@@l:
mov al,[si-1]
cmp al,'/'
jz @@e
cmp al,'\'
jz @@e
cmp al,':'
jz @@e
@@f: dec si
cmp si,dx
jnz @@l
@@e: pop dx
ret
endp
endm
macro _PATHCOPY ;Pfad-Copy kopiert nur den Pfad aus DS:SI nach ES:DI
;DI zeigt am Ende hinter die Null, SI zeigt auf Name
;(fast schon ein perfektes FSPLIT, oder?)
_SEEKNAME
proc PathCopy
push cx dx
mov dx,si
call SeekName
mov cx,si
sub cx,dx
xchg si,dx
rep movsb ;schaufeln, notfalls 0 Bytes
xor al,al
stosb ;Abschlu-Null
xchg dx,si
pop dx cx
ret
endp
endm
macro _SEEKEXT ;Extension suchen, CY=1 wenn keine vorhanden
proc SeekExt
cld
call SeekName
@@se1: lodsb
cmp al,1
jc @@see
cmp al,'.'
jnz @@se1
@@see: dec si
ret
endp
endm
macro _SEEKINPATH ;Sucht DS:DI im Pfad (endlich mal was richtiges!)
;bentigt _STRCPX, _STRCPR, _SEEKNAME und _SEEKEXT
proc SeekInPath
@@dta equ bp-2ch
@@oldta equ dword bp-30h
@@path equ dword bp-34h
@@name equ dword bp-38h
@@src equ dword bp-3ch
@@dest equ dword bp-40h
cld
entr 38h ;2ch fr DTA, 4 fr Adresse zum alten DTA?
;4 fr PATH-Adresse, 4 fr Quell-Adresse
push ds si es di bx dx
; sds <@@src>,si
; ses <@@dest>,di
DOS 2fh ;GetDTA
ses <@@oldta>,bx
LD ds,ss
lea dx,[@@dta]
DOS 1ah ;SetDTA
lds si,[@@src]
les di,[@@dest]
call StrCpy
call @@ff ;hidden, system, r/o seien erlaubt!
jnc @@e ;bereits alles OKAY!
lds si,[@@src]
mov dx,si
call SeekName
sds <@@name>,si
sub si,dx
jz @@1
cmp si,2
stc
jnz @@e ;Fehler, da Pfad angegeben wurde
mov si,dx
cmp [by si+1],':' ;Laufwerksbezeichner?
stc
jnz @@e
@@1: LD ds,cs
mov si,ofs @@path$
call GetEnv
jc @@e ;Armer Rechner! (Kein PATH definiert)
ses <@@path>,di
@@3: lds si,[@@path]
cmp [by si-1],1
jc @@e ;raus mit Fehler
les di,[@@dest]
mov ah,';'
call StrCpH
sds <@@path>,si ;Neue Position speichern
mov [by es:di-1],'\';auf die Null drauf
lds si,[@@name]
call StrCpy
call @@ff ;FindFirst
jc @@3
@@e: pushf
lds dx,[@@oldta]
DOS 1ah ;SetDTA
popf
; lds si,[@@src]
; les di,[@@dest]
pop dx bx di es si ds
leav
ret
@@ff: ;Spezielles FindFirst via @@dest und evtl. Suffix anbammeln
lds si,[@@dest]
mov dx,si
call SeekExt
jnc @@ff1 ;Yeah, da is shoa eine Extension!
LD es,cs
mov di,ofs @@com$
push si
call StrCpR ;Revers!
call @@ffu
pop si
jnc @@ffe ;Schon gefunden!
call StrCpR ;jetzt kommt die Echse!
@@ff1: call @@ffu
@@ffe: ret
@@ffu: push cx
mov cx,7
DOS 4eh
pop cx
ret
@@com$ db '.COM',0
db '.EXE',0
@@path$ db 'PATH',0
endp
endm
macro _FEXPAND
proc FExpand
push si dx
cmp [by si],0 ;Leerstring?
jz @@1
cmp [by si+1],':' ;Laufwerk angegeben?
jnz @@1 ;nein
lodsw
jr @@2
@@1: DOS 19h ;Laufwerk->AL
add al,'A'
mov ah,':'
@@2: stosw ;Laufwerk und Doppelpunkt bernehmen
bres al,bit 5
sub al,'@'
mov dl,al ;Laufwerk nach DL fr PWD
lodsb
cmp al,'\'
jz @@3
cmp al,'/' ;fr die ewig gestrigen...
jz @@3
dec si ;aufs erste Zeichen (nach ":")
mov al,'\'
stosb
push ds
LD ds,es
xchg si,di ;Puffer ist DS:SI
DOS 47h ;"PWD"
SKEND ;Abschlu-Null suchen
xchg di,si
pop ds
cmp [by si],0 ;Quellstring leer?
jz @@e
dec di ;auf die Null
@@3: mov al,'\'
cmp [by es:di-1],'\' ;Schon ein Backslash? (DOS knnte Leerstring liefern!)
jz @@4
stosb
@@4: call strcpy
@@e: pop dx si
ret
endp FExpand
endm
macro _zkout2
proc zkout2
push bx
mov bx,1 ;Standardausgabe
call zkouth ;NEU: schneller als Einzelzeichenausgabe!
pop bx
ret
endp
proc zkouth ;Ausgabe via Handle BX
push cx si
mov si,dx
mov cx,-1
cld
@@1: inc cx ;Lnge in CX berechnen
lodsb
or al,al
jnz @@1
pop si
DOS 40h ;Blockwrite ist schneller!!
pop cx
ret
endp
endm
macro _zkout ;Ausgabe nullterminierte Zeichenkette via SI:DX
;VR: AL,F (Stark rudimentr...)
proc zkout
xchg dx,si
call zkout2
xchg si,dx
ret
endp
endm
macro _STRCPY ;StringCopy normal dx:si->es:di
strcpy:
lodsb
stosb
or al,al
jnz strcpy
ret
endm
macro _STRCPR ;StringCopy revers
_STRCPY
strcpr: xchg si,di
EX ds,es
call strcpy
EX ds,es
xchg si,di
ret
endm
macro _STRCPX ;erweitertes StrCpy: mit Weiraum am Ende
proc strcpx
xor ah,ah
strcph: ;kopiert bis Weiraum ODER dem Zeichen in AH!
@@2: lodsb
cmp al,ah
jz @@3
call ChkWS
jnz @@1
@@3: mov al,0
@@1: stosb
jnz @@2
ret
endp
_CHKWS
endm
macro _STRCOMP
proc StrComp ;richtiges StringCompare! Z=0: Strings ungleich
;CY=1: String ES:DI grer als String DS:SI VR: Flags
push si di
cld
jr @@1
@@2: cmp [by si-1],0
jz @@e ;Beide Strings zu Ende
@@1: cmpsb
jz @@2
@@e: pop di si
ret
endp
endm
macro _STRICOMP
proc StrIComp ;StringCompare! mit simplem UpCase, Z=0: Strings ungleich
;CY=1: String ES:DI grer als String DS:SI VR: Flags
push ax si di
cld
jr @@1
@@2:
or ax,ax
jz @@e ;Beide Strings zu Ende
@@1: lodsb
call UpCase
xchg ah,al
mov al,[es:di]
inc di
call UpCase
cmp ah,al
jz @@2
@@e: pop di si ax
ret
endp
endm
macro _INSTR
proc InStr ;InStr (Pascal: POS) liefert in BX Position des
;Strings DS:SI in ES:DI
;DS:SI darf nicht leer sein!
;BX=0: Position Null!
;CY=1: Nicht gefunden, dann BX unverndert
push ax cx si di
mov cx,-1
cld
lodsb
cmp al,1
jc @@e ;Fehler: Suchstring leer
@@3: dec si ;aufs 1. Zeichen kurzer String!
lodsb
@@0: cmp [by es:di],1
jc @@e ;Groer String zu Ende
inc cx
scasb
jnz @@0 ;Ungleicher 1. Buchstabe
push si di
@@1: lodsb
or al,al
jz @@2
scasb
jz @@1
@@2: pop di si
jnz @@3
xchg bx,cx
@@e: pop di si cx ax
ret
endp
endm
macro _INSTRI
proc InStrI ;InStr (Pascal: POS) liefert in BX Position des
;Strings DS:SI in ES:DI
;DS:SI darf nicht leer sein!
;BX=0: Position Null!
;CY=1: Nicht gefunden, dann BX unverndert
push ax cx si di
mov cx,-1
cld
lodsb
cmp al,1
jc @@e ;Fehler: Suchstring leer
@@3: dec si ;aufs 1. Zeichen kurzer String!
lodsb
call UpCase
xchg ah,al ;'hochladen'
@@0: mov al,[es:di]
inc di
cmp al,1
jc @@e ;Groer String zu Ende
inc cx
call UpCase
cmp ah,al
jnz @@0 ;Ungleicher 1. Buchstabe
push si di
@@1: lodsb
or al,al
jz @@2
call UpCase
xchg ah,al ;'hochladen'
mov al,[es:di]
inc di
call UpCase
cmp ah,al
jz @@1
@@2: pop di si
jnz @@3
xchg bx,cx
@@e: pop di si cx ax
ret
endp
endm
macro _YESNO
proc YesNo ;Z=1 wenn JA
push dx ds cs
pop ds
PRINT @@3
@@1:
DOS 8
call UpCase
cmp al,'Y'
jz @@2
cmp al,'N'
jnz @@1
@@2: call ochr
call crlf
cmp al,'Y'
pop ds dx
ret
@@3: db '? [Y/N] $'
endp
_CRLF
endm
macro _JANEIN
proc JaNein ;Z=1 wenn JA
push dx ds cs
pop ds
PRINT @@3
@@1:
DOS 8
call UpCase
cmp al,'J'
jz @@2
cmp al,'N'
jnz @@1
@@2: call ochr
call crlf
cmp al,'J'
pop ds dx
ret
@@3: db '? [J/N] $'
endp
_CRLF
endm
macro _INLIN
proc Inlin ;Primitive Stringeingabe mit Echo, VR: AX
mov ah,1 ;Funktions-Nummer!
jr InLine
InSec: mov ah,8 ;ohne Echo frs Pawort
InLine: ;ES:DI=Stringpuffer, CX=max. Zeichenzahl+1 = Puffergre
push dx cx
mov dx,di ;Anfang merken
@@4: dec cx
@@3: mov [by es:di],0 ;Ende-Null
DOS ;ohne Echo
cmp al,8 ;Backstep?
jz @@1
cmp al,13 ;Enter?
jz @@2
jcxz @@31 ;Puffer voll
stosb
jr @@4
@@31: cmp ah,8 ;echolos?
jz @@3
jr @@5
@@1: cmp dx,di
jz @@3 ;wirkungslos verpuffen lassen
inc cx
dec di
mov al,' '
call ochr
@@5: mov al,8
call ochr
jr @@3 ;Null trgt sich von selbst ein
@@2: call crlf ;Zweckmig: neue Zeile!
xchg di,dx
pop dx cx
ret
endp
endm
macro _INSEC
proc InSec ;Primitive Stringeingabe ohne Echo frs Pawort
;ES:DI=Stringpuffer, CX=max. Zeichenzahl+1 = Puffergre
push dx cx
mov dx,di ;Anfang merken
cld
@@4: dec cx
@@3: mov [by es:di],0 ;Ende-Null
DOS 8 ;ohne Echo
cmp al,ah ;Backstep?
jz @@1
cmp al,13 ;Enter?
jz @@2
jcxz @@3 ;Puffer voll
stosb
jr @@4
@@1: cmp dx,di
jz @@3 ;wirkungslos verpuffen lassen
inc cx
dec di
jz @@3
@@2: call crlf ;Zweckmig: neue Zeile!
xchg di,dx
pop dx cx
ret
endp
endm
macro _ERRMG ;Deutsche DOS-Fehlermeldungen
;erfordert ZKOUT2, AHEX
proc errmg
mov cl,al
mov ch,0
WrStr @@1$
mov al,cl
call ahex
or al,al
jz @@2
cmp al,9
jnc @@2
mov si,ofs @@2$
@@1: SKEND
loop @@1
WrStr @@3$
mov dx,si
call zkout2 ;Zeichenkettenausgabe
@@2: jmp crlf
@@1$: db 'DOS-Fehler $',0
@@3$: db ': ',0
@@2$: db 'Unbekannte Funktionsnummer',0
db 'Datei nicht gefunden',0
db 'Pfad nicht gefunden',0
db 'Kein Handle verfgbar',0
db 'Zugriff verweigert',0
db 'Ungltiges Handle',0
db 'Speichersteuerblcke zerstrt',0
db 'Nicht gengend Speicher',0
endp
endm
macro _ERRME ;Englische DOS-Fehlermeldungen
;erfordert ZKOUT2, AHEX
proc errme
mov cl,al
mov ch,0
WrStr @@1$
mov al,cl
call ahex
or al,al
jz @@2
cmp al,9
jnc @@2
mov si,ofs @@2$
@@1: SKEND
loop @@1
WrStr @@3$
mov dx,si
call zkout2 ;Zeichenkettenausgabe
@@2: jmp crlf
@@1$: db 'DOS-error 0x',0
@@3$: db ': ',0
@@2$: db 'Invalid function number',0
db 'File not found',0
db 'Path not found',0
db 'No handle available',0
db 'Access denied',0
db 'Invalid handle',0
db 'MCB's destroyed',0
db 'Insufficient memory',0
endp
endm
| Vorgefundene Kodierung: UTF-8 | 0
|