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 (Grobuchst. nicht zwingend!) ohne '=', DS auf PSP-Seg.
PA: ES:DI ASCOOZ 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.)
_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
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
@@src equ dword bp-38h
@@dest equ dword bp-3ch
@@name equ dword bp-40h
cld
entr 40h ;2ch fr DTA, 4 fr Adresse zum alten DTA?
;4 fr PATH-Adresse, 4 fr Quell-Adresse
push 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
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 _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
Detected encoding: UTF-8 | 0
|