home *** CD-ROM | disk | FTP | other *** search
- TITLE FChars - Code fuer Turbo-Pascal-Funktionen zur
- SUBTTL Bearbeitung von NUL-terminierten Strings im C-Format
-
- ; goes along with FIDO unit to add Borland Pascal 7.0's Strings functions to
- ; prior versions
- ; ***************************************************************************
-
- ; RELEASE 1.0 - as first contained in the file PRUS101.LZH
- ; by Sieghard Schicktanz, 2:2480/642.25, GERMANY
-
- ; --------------------------------------------
- ; organized for Fido's PASCAL related echoes
- ; --------------------------------------------
-
- ; 08/02/1994 to --/--/---- by Sieghard Schicktanz, 2:2480/642.25, GERMANY
-
-
- ; As far as third party copyrights are not violated this
- ; source code is hereby placed to the public domain. Use
- ; it whatever way you want, but use AT YOUR OWN RISK.
-
- ; In case you should modify the source rather send your
- ; modifications to the unit's current organizer (see above for
- ; NM address) than to spread it on your own. This will help to
- ; keep the unit updated and grant a certain standard to all
- ; other users as well.
-
- ; The unit is currently still under work. So it might greatly
- ; benefit of your participation.
-
- ; Those who contributed to the following piece of source,
- ; listed in alphabethical order:
- ; ================================================================
- ; Andrew Eigus, Sieghard Schicktanz, ...
- ; ================================================================
- ; YOUR NAME WILL APPEAR HERE IF YOU CONTRIBUTE USEFUL SOURCE.
-
- ; Credits in your own programs are as welcome as unnecessary.
-
- ; ***************************************************************************
-
- .MODEL TPASCAL
-
- PUBLIC Str2PChar, StrCat, StrComp, StrCopy, StrECopy
- PUBlIC StrEnd, StrLCat, StrLComp, StrLCopy
- PUBlIC StrLen, StrPas, StrRScan, StrScan, StrSkip
- ; %StrPCopy% implemented differently!
-
- ; First, let's declare a couple of abbreviations and macros
- ; that should make the code more readable
-
- pntr EQU DWORD ; this relates to the standard Pascal pointer type
- Rseg EQU DX ; return registers used for
- Roff EQU AX ; pointer values and
- Rint EQU AX ; integer values by Turbo Pascal
-
- SetUp MACRO Regs ; this will be used to set up segment registers
- LOCAL @reg
-
- CLD
- IRP @reg, <Regs>
- PUSH @reg
- ENDM
- ENDM
-
- CleanUp MACRO Regs ; this restores segments and returns cleanly
- LOCAL @reg
-
- IRP @reg, <Regs>
- POP @reg
- ENDM
- RET
- ENDM
-
-
- LOCALS @@ ; tell the assembler how locals are marked
-
- ; Now to the real thing - function code starts below
-
- .CODE ; use this bloody segment
-
-
- Str2PChar PROC FAR source: pntr
- ; FUNCTION Str2PChar (str: string): PChar;
-
- SetUp <DS, ES>
- CLD
- LES DI, source ; this is done in place!
- LDS SI, source ; so target is same as source
- SUB CX, CX
- LODSB ; get count byte
- MOV CL, AL
- JCXZ @@nix ; nothing to do?
-
- REP MOVSB ; move string down a notch
- SUB AL, AL ; and stick the NUL terminator
- @@nix:
- STOSB ; to the end
- LES DI, source ; now return
- MOV Rseg, ES ; input address
- MOV Roff, DI ; as output
- CleanUp <ES, DS>
-
- Str2PChar ENDP
-
-
- StrCat PROC FAR dest: pntr, source: pntr
- ; FUNCTION StrCat (dest, source: PChar): PChar;
-
- SetUp <DS, ES>
- CLD
- LES DI, dest
- TEST BYTE PTR ES:[DI], -1 ; see if anything to do
- JZ @@nix ; no, is empty
-
- SUB AL, AL ; scan for NUL
- SUB CX, CX ; as much as 64 KB
- REPNZ SCASB
- @@nix:
- JMP copy_string ; copy other one behind
-
- StrCat ENDP
-
-
- StrComp PROC FAR dest: pntr, source: pntr
- ; FUNCTION StrComp (dest, source: PChar): integer;
-
- SetUp <DS, ES>
- CLD
- LDS SI, source
- LES DI, dest
- @@next:
- LODSB ; get current source char
- SCASB ; compare with target char
- JA @@more ; not equal?
- JB @@less ; what's the difference?
-
- OR AL, AL ; hit terminator?
- JNZ @@next ; not yet, continue
- @@null:
- SUB Rint, Rint ; all compared ok
- @@done:
- CleanUp <ES, DS>
-
- @@less:
- MOV Rint, -1 ; dest was "greater"
- JMP SHORT @@done
- @@more:
- MOV Rint, 1 ; dest was "less"
- JMP SHORT @@done
-
- StrComp ENDP
-
-
- StrCopy PROC FAR dest: pntr, source: pntr
- ; FUNCTION StrCopy (dest, source: PChar): PChar;
-
- SetUp <DS, ES>
- CLD
- LES DI, dest
- copy_string: ; an entry from elsewhere...
- LDS SI, source ; (see below)
- @@next:
- LODSB ; copy characters
- STOSB
- OR AL, AL ; till NUL terminator
- JNZ @@next
-
- LES DI, dest
- MOV Rseg, ES
- MOV Roff, DI
- CleanUp <ES, DS>
-
- StrCopy ENDP
-
-
- StrECopy PROC FAR dest: pntr, source: pntr
- ; FUNCTION StrECopy (dest, source: PChar): PChar;
-
- SetUp <DS, ES>
- LDS SI, source
- LES DI, dest
- CLD
- @@next:
- LODSB ; copy characters
- STOSB
- OR AL, AL ; till NUL terminator
- JNZ @@next
-
- DEC DI ; went one too far
- MOV Rseg, ES ; set up return registers
- MOV Roff, DI ; for pointer value
- CleanUp <ES, DS>
-
- StrECopy ENDP
-
-
- StrEnd PROC FAR source: pntr
- ; FUNCTION StrEnd (source: PChar): PChar;
-
- SetUp ES
- CLD
- MOV CX, -1
- LES DI, source
- SUB AL, AL ; look out for NUL
- REPNZ SCASB
- DEC DI ; was just behind
- MOV Rseg, ES ; and return pointer to
- MOV Roff, DI ; terminator
- CleanUp ES
-
- StrEnd ENDP
-
-
- StrLCat PROC FAR dest: pntr, source: pntr, n: WORD
- ; FUNCTION StrLCat (dest, source: PChar; n: byte): PChar;
-
- SetUp <DS, ES>
- CLD
- LES DI, dest
- TEST BYTE PTR ES:[DI], -1 ; see if anything to do
- JZ @@nix ; no, is empty
-
- SUB AL, AL ; scan for NUL
- SUB CX, CX ; as much as 64 KB
- REPNZ SCASB
- @@nix:
- JMP copy_n_chars ; copy other one behind
-
- StrLCat ENDP
-
-
- StrLComp PROC FAR dest: pntr, source: pntr, n: WORD
- ; FUNCTION StrLComp (dest, source: PChar; n: byte): integer;
-
- SetUp <DS, ES>
- MOV CX, n ; get compare count
- JCXZ @@null ; nothing to do?
-
- LDS SI, source
- LES DI, dest
- CLD
- @@next:
- LODSB ; get current source char
- SCASB ; compare with target char
- JA @@more ; not equal?
- JB @@less ; what's the difference?
-
- OR AL, AL ; hit terminator?
- LOOPNZ @@next ; not yet, continue
- @@null:
- SUB Rint, Rint ; all compared ok
- @@done:
- CleanUp <ES, DS>
-
- @@less:
- MOV Rint, -1 ; dest was "greater"
- JMP SHORT @@done
- @@more:
- MOV Rint, 1 ; dest was "less"
- JMP SHORT @@done
-
- StrLComp ENDP
-
-
- StrLCopy PROC FAR dest: pntr, source: pntr, n: WORD
-
- SetUp <DS, ES>
- CLD
- LES DI, dest
- copy_n_chars:
- MOV CX, n
- JCXZ @@nix
- LDS SI, source
- REP MOVSB
- @@nix:
- SUB AL, AL
- STOSB
- LES DI, dest ; reset to beginning
- MOV Rseg, ES ; to be passed
- MOV Roff, DI ; back
- CleanUp <ES, DS>
-
- StrLCopy ENDP
-
-
- StrLen PROC FAR source: pntr
- ; FUNCTION StrLen (source: PChar): word;
-
- SetUp ES ; not _really_ needed...
- SUB CX, CX ; assume empty
- LES DI, source ; now get the address
- TEST BYTE PTR ES:[DI], -1 ; and test the first char
- JZ @@nix ; really empty!
-
- CLD ; _always_ go upstairs!
- DEC CX
- SUB AL, AL ; scan for NUL byte
- REPNZ SCASB ; within string
- INC CX ; convert counter register
- NOT CX ; to distance from start
- @@nix:
- MOV Rint, CX ; and return in result reg
- CleanUp ES
-
- StrLen ENDP
-
-
- StrPas PROC FAR cstring: pntr RETURNS pstring: pntr
- ; FUNCTION StrPas (source: PChar): string;
-
- SetUp <DS, ES>
- LDS SI, cstring ; this is the source
- MOV AX, DS
- OR AX, SI ; check for NIL
- JZ @@thru ; if so we're done
-
- LES DI, pstring ; the target is implicitely
- CLD ; passed by the compiler!
- SUB AX, AX ; clear length counter
- STOSB ; skip length byte
- @@next:
- LODSB ; now check this char
- OR AL, AL ; hit NUL terminator?
- JZ @@thru ; then we're done
-
- INC AH ; else increment counter
- JZ @@over
-
- STOSB ; and copy this one over
- JMP @@next ; continue
- @@over:
- DEC AH ; don't count terminator
- @@thru:
- MOV AL, AH ; put count into correct register
- LES DI, pstring ; point at start of result
- STOSB ; and put count there
- CleanUp <ES, DS>
-
- StrPas ENDP
-
- COMMENT %
-
- StrPCopy PROC FAR dest: pntr, source: pntr
- ; FUNCTION StrPCopy (dest: PChar; source: string): PChar;
-
- SetUp <DS, ES>
- LES DI, dest
- LDS SI, source
- SUB CX, CX
- LODSB
- MOV CL, AL
- JCXZ @@nix
- CLD
- REP MOVSB
- SUB AL, AL
- @@nix:
- STOSB
- LES DI, dest
- MOV Rseg, ES
- MOV Roff, DI
- CleanUp <ES, DS>
-
- StrPCopy ENDP
- %
-
- StrScan PROC FAR source: pntr, chr: WORD
- ; FUNCTION StrScan (source: PChar; ch: char): PChar;
-
- SetUp DS
- CLD
- LDS SI, source
- MOV DX, chr
- @@next:
- LODSB
- OR AL, AL ; see if at end already
- JZ @@null ; yes, hit terminator
-
- CMP AL, DL ; is it requested char?
- JNZ @@next ; no, get next one
- @@found:
- MOV Rseg, DS ; return pointer
- MOV Roff, SI ; to target char
- DEC Roff ; went one too far
- CleanUp DS
- @@null:
- SUB Rseg, Rseg ; else return NIL
- MOV Roff, Rseg
- CleanUp DS
-
- StrScan ENDP
-
-
- StrRScan PROC FAR source: pntr, chr: WORD
- ; FUNCTION StrRScan (source: PChar; ch: char): PChar;
-
- SetUp ES
- LES DI, source ; now get the address
- TEST BYTE PTR ES:[DI], -1 ; and test the first char
- JZ @@null ; cannot be!
-
- CLD
- MOV CX, -1
- SUB AL, AL ; find terminating NUL
- REPNZ SCASB
- DEC DI ; revert to terminator
- NOT CX ; to real string length
- MOV AX, chr ; get what to search for
- STD ; do it backwards now!
- REPNZ SCASB ; and off we go!
- JNZ @@null ; nope, not found
- @@found:
- MOV Rseg, ES ; return pointer
- MOV Roff, DI ; to target char
- INC Roff ; went one too far
- CLD ; just for safety
- CleanUp ES
- @@null:
- SUB Rseg, Rseg ; else return NIL
- MOV Roff, Rseg
- CleanUp ES
-
- StrRScan ENDP
-
-
- StrSkip PROC FAR source: pntr
- ; FUNCTION StrSkip (source: PChar): PChar;
-
- SetUp ES
- MOV CX, -1
- LES DI, source
- SUB AL, AL ; look out for NUL
- CLD
- REPNZ SCASB
- MOV Rseg, ES ; and return pointer to
- MOV Roff, DI ; just behind
- CleanUp ES
-
- StrSkip ENDP
-
- END
-