home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- TITLE String manipulation -- LARGE MEM (FAR)
- NAME StrPackL
-
- ; Use this file in any way that pleases you.
-
- DOSSEG
- .MODEL LARGE
-
- .XLIST
- XchgSeg MACRO Seg1,Seg2
- Push Seg1 ; Save the Segment register
- Push Seg2 ; Save the Segment register
- Pop Seg1 ; Put Segment here
- Pop Seg2 ; The same for the first
- ENDM
- .LIST
-
-
- .DATA?
- TempW DW ? ; Temporary Word size VAR
- TempW2 DW ? ; Another temporary word if needed
- TempB DB ? ; Temporary Byte
-
-
-
- .CODE
-
- PUBLIC Length, Append, Concat, Extract,
- PUBLIC Split, LowerCase, UpperCase, Proper
- PUBLIC Trim, Checksum, Compare
-
-
- Length Proc
- ;-----------------------------------------------------------------------------;
- ; Returns the length of an asciiz string. ;
- ; INPUT: ;
- ; DS:SI = Address of ASCIIZ string ;
- ; OUTPUT: ;
- ; AX = Length of string (Not including the NULL char at end ;
- ;-----------------------------------------------------------------------------;
- Push Di ;
- Push Cx ; Save them
- Push Es ;
- ;
- Xor Cx,Cx ; Clear to 0
- Not Cx ; And flip the bits
- Cld ;
- Mov Di,Si ;
- Push Ds ;
- Pop Es ;
- Mov Al,0 ; Search
- Repnz Scasb ; Scan for the 0
- Not Cx ; Flip the bits back
- Mov Ax,Cx ; Put count Here
- Dec Ax ; And take one out -- do not include 0
- ;
- Pop Es ;
- Pop Cx ; Get the old Cx
- Pop Di ; Get the ols si
- Ret ; And exit
- Length Endp
-
-
-
- Append Proc
- ;-----------------------------------------------------------------------------;
- ; Appends Second string onto the first string in memory. ;
- ; INPUT: ;
- ; DS:SI = Address of First string. ;
- ; ES:DI = Address of Second string (one to be appedned ;
- ; OUTPUT: ;
- ; Nothing changed except first string is now Firststring+Secondstring ;
- ;-----------------------------------------------------------------------------;
- Push Ax ; Save all the registers Used
- Push Cx ;
- Push Si ;
- Push Di ;
- Pushf ; And the flags
- ;
- Call Length ; Get the length of first string
- Add Si,Ax ; Add to get to end of first
- Xchg Si,Di ; Switch to
- XchgSeg Ds,Es ; Exchange these segment registers
- Call Length ; Get the length of the second string
- Mov Cx,Ax ; Count
- Inc Cx ; Snag the ASCIIZ byte also
- Cld ; Up
- Rep Movsb ; Transfer
- ;
- Popf ; Pop everything used
- Pop Di ;
- Pop Si ;
- Pop Cx ;
- Pop Ax ;
- Ret ; And return
- Append Endp ;
-
-
- Concat Proc
- ;-----------------------------------------------------------------------------;
- ; Works like Append except neither of the two orugunal strings are touched, ;
- ; but the result is placed in another location all together (C := A+B) ;
- ; INPUT: ;
- ; DS:SI = Address of First String ;
- ; DS:BX = Address of Second String ;
- ; ES:DI = Address to place (First String + Second String) ;
- ; OUTPUT: ;
- ; AX = Length of resulting string ;
- ;-----------------------------------------------------------------------------;
- Push Bx ;
- Push Cx ;
- Push Dx ;
- Push Si ;
- Push Di ;
- ;
- Cld ; Dest is ES:DI
- ; Get some string lengths
- Call Length ; String 1
- Mov Cx,Ax ; Length of string 1 in CX
- Xchg Bx,Si ;
- Call Length ;
- Xchg Bx,Si ;
- Mov Dx,Ax ; Length of String 2 in DX
- Add Ax,Cx ; Get resulting length
- Mov TempW,Ax ; Save it for temp
- ; Now,
- Rep Movsb ; Transfer part one
- Xchg Dx,Cx ; Switch
- Xchg Bx,Si ; Switch
- Inc Cx ; Include the ASCIIZ NULL
- Rep Movsb ; Move this
- ; We are done
- Pop Di ;
- Pop Si ;
- Pop Dx ;
- Pop Cx ;
- Pop Bx ;
- Mov Ax,TempW ; Get the resulting count
- Ret ; And return
- Concat Endp
-
-
- Extract Proc
- ;-----------------------------------------------------------------------------;
- ; EXtracts a number of chars from a given string and puts in dest. ;
- ; INPUT ;
- ; DS:SI = The address of string to be extracted from (source) ;
- ; ES:DI = Destination address of the new string ;
- ; AX = Number of chars to extract ;
- ; OUTPUT ;
- ; ES:DI = address of first char of new string. ;
- ; everything else is actually unchanged. ;
- ;-----------------------------------------------------------------------------;
- Push Ax ;
- Push Cx ;
- Push Si ;
- ;
- Mov Cx,Ax ; Put this here
- Add Si,Ax ; Add offset
- Mov Al,0 ;
- Cld ;
- Rep Movsb ; Move it -- HA and bingo
- Stosb ; Save an ASCIIZ char
- ;
- Pop Si ;
- Pop Cx ;
- Pop Ax ;
- Ret ;
- Extract Endp
-
-
- Split Proc
- ;-----------------------------------------------------------------------------;
- ; Splits a given ASCIIZ string into 2 distinct ASCIIZ string. ;
- ; INPUT ;
- ; DS:SI = Address of string to be split. ;
- ; BX = Offset into DS:SI where the start of split occurs. ;
- ; ES:DI = OFfset of the second half of DS:SI (split) is to be placed. ;
- ; OUTPUT ;
- ; ES:DI = Address of string that came from string one. ;
- ; AX = New Length of string that was DS:SI ;
- ; BX = Length of the string that is found in ES:DI ;
- ; Thus... ;
- ; "The green roof on the lawn",0 split at r of roof ;
- ; BECOMES... ;
- ; "The green ",0 (DS:SI) [New Length in AX] AND ;
- ; "roof on the lawn",0 (ES:DI) [New Length in BX] ;
- ;-----------------------------------------------------------------------------;
- Push Cx ;
- Push Dx ;
- Push Si ;
- Push Di ;
- Push Bp ;
- Cld ;
- ;
- Push Si ;
- Call Length ; Get the length
- Mov Dx,Ax ;
- Add Si,Bx ; Add this
- Call Length ; Get the length of second string
- Mov Bp,Ax ; Save length of new string for later
- Mov Cx,Ax ; Grab that length
- Inc Cx ; Include the null
- Rep Movsb ; Move it including the null
- Pop Si ; Get the offset back
- ;
- Mov BYTE PTR [Bx+Si],0 ; Make it null
- ;
- Sub Dx,Bp ; Get difference
- Mov Ax,Dx ;
- Mov Bx,Bp ;
- ;
- Pop Bp ;
- Pop Di ;
- Pop Si ;
- Pop Dx ;
- Pop Cx ;
- Ret ;
- Split Endp
-
-
- LowerCase Proc
- ;-----------------------------------------------------------------------------;
- ; Converts entire input string to lowercase. ;
- ; INPUT : ;
- ; DS:SI = Address of source string. ;
- ; ES:DI = Address of new string exactly like first exept all lc. ;
- ; OUTPUT : ;
- ; ES:DI = Address of New string all in lowercase. ;
- ;-----------------------------------------------------------------------------;
- Push Ax ;
- Push Cx ;
- Push Si ;
- Push Di ;
- ;
- Cld ; Yep
- Call Length ; Get the Length
- Mov Cx,Ax ; Put it for the count
- _UtoLtop: Lodsb ; Get it
- Cmp Al,'A' ; Well
- Jb @F ; Nope
- Cmp Al,'Z' ; Well...
- Ja @F ; Nope skip add
- Add Al,20h ; Convert to lower case
- @@: Stosb ;
- Loop _UtoLtop ; Back
- ;
- Pop Di ;
- Pop Si ;
- Pop Cx ;
- Pop Ax ;
- Ret ;
- LowerCase Endp
-
-
- UpperCase Proc
- ;-----------------------------------------------------------------------------;
- ; Converts entire input string to uppercase. ;
- ; INPUT : ;
- ; DS:SI = Source string. ;
- ; ES:DI = Address to place new string. ;
- ; OUTPUT: ;
- ; ES:DI = address of new string like souce but all to uppercase. ;
- ;-----------------------------------------------------------------------------;
- Push Ax ;
- Push Si ;
- Push Di ;
- ;
- Cld ;
- Call Length ; Get the length
- Mov Cx,Ax ; For the count
- _LtoUtop: Lodsb ; Grab
- Cmp Al,'a' ; Well
- Jb @F ; Foreward
- Cmp Al,'z' ; Well,///
- Ja @F ; skip the subtract
- Sub Al,20h ; Take it out
- @@: Stosb ; Save it
- Loop _LtoUtop ; Hmm...
- ;
- Pop Di ;
- Pop Si ;
- Pop Ax ;
- Ret ;
- UpperCase Endp
-
-
-
- Proper Proc
- ;-----------------------------------------------------------------------------;
- ; Make a given input string to proper format. i. e. ;
- ; "THIS IS A STRING",0 made proper would look like... ;
- ; "This Is A String",0 ;
- ; INPUT : ;
- ; DS:SI = Source input string. ;
- ; ES:DI = Destination address. ;
- ; OUTPUT: ;
- ; ES:DI = address of output proper string. ;
- ;-----------------------------------------------------------------------------;
- Push Ax ;
- Push Si ;
- Push Di ;
- ;
- Cld ;
- ; First convert to lowercase
- Call LowerCase ; Make it all like lower case
- ; Now search and do.
- Mov Si,Di ; Neww source address
- XchgSeg Ds,Es ;
- Mov Ah,0 ; Clear our flag
- _FindWord: Lodsb ;
- Cmp Al,0 ; Are we done
- Je _ProperDone ;
- Cmp Al,'a' ; well?
- Jb @F ;
- Cmp Al,'z' ;
- Ja @F ;
- Add Al,-20h ; Ok
- Dec Ah ;
- @@: Stosb ;
- Or Ah,Ah ;
- Jns _FindWord ; Not negative then keep finding
- ; Found word and converted
- _FindDelim: Lodsb ; Grab
- Cmp Al,0 ;
- Je _ProperDone ;
- Cmp Al,'a' ; Well
- Jae _Pt2xx ;
- Jmp SHORT _DFp;
- _Pt2xx: Cmp Al,'z' ; Ok?
- Jbe @F ; Skip the flag reset
- _DFp: Inc Ah ; Back to 0
- @@: Stosb ;
- Or Ah,Ah ;
- Js _FindDelim ; While negative keep searching
- Jmp _FindWord ; Back to word search
- _ProperDone: Stosb ; Save the ASCIIZ
- ;
- XchgSeg Ds,Es ; Back to what these were
- ;
- Pop Di ;
- Pop Si ;
- Pop Ax ;
- Ret ;
- Proper Endp
-
-
- Trim PROC
- ;-----------------------------------------------------------------------------;
- ; Trims an input string by removing all the leading and trailing spaces. ;
- ; also leaves one space in between each word and if comma then it goes ;
- ; the comma then space, if period then . and if not at end then 2 spaces ;
- ; INPUT: ;
- ; DS:SI = address of string to be trimmed. ;
- ; ES:DI = destination of new string. ;
- ; OUTPUT: ;
- ; AX = length of resulting new sentence and of course.. ;
- ; ES:DI = address of new string. NOTE THAT the original string is intact. ;
- ;-----------------------------------------------------------------------------;
- Push Cx ;
- Push Dx ;
- Push Si ;
- Push Di ;
- ;
- Cld ; Upper
- Call Length ; Get the length of the monstocity
- Mov Cx,Ax ; This is our count down counter
- Xor Dx,Dx ; This is our count up counter
- Mov Ah,' ' ; Start the flag with a space
- _TrimTlop: Jcxz _TrimBlop ; If we are done then exit
- Lodsb ; Get a char
- Dec Cx ; Down one
- Cmp Al,' ' ; Are we pointing to a space
- Jne @F ; Forweward
- Cmp Ah,' ' ; If we find a space and we had a space
- Je _TrimTlop ; Then ignore it and we continue
- Cmp Ah,'.' ; But if we had a period
- Jne _lastwaschar; ---
- Stosb ; Store the space and
- Inc Dx ;
- _lastwaschar: Stosb ; Otherwise we store the space
- Xchg Ah,Al ; And switch the bytes
- Inc Dx ; Add one for our length
- Jmp _TrimTlop ; And back we go
- @@: Cmp Al,',' ; Are we pinting to a comma
- Jne @F ; Nope so we jump to next test
- Stosb ; Save the comma
- Inc Dx ; Counter + 1
- Mov Al,' ' ; and one space
- Stosb ; After the comma
- Inc Dx ; Counter + 1
- Xchg Ah,Al ; Switch to tell our last thing
- Jmp _TrimTlop ; Back to do another
- @@: Stosb ; Save the char (period or otherwise)
- Inc Dx ; Hmm
- Xchg Ah,Al ; Specify the last char taken
- Jmp _TrimTlop ;
- _TrimBlop: Mov Al,0 ; Put a null here
- Stosb ; Save the null
- Mov TempW,Dx ;
- ;
- Pop Di ;
- Pop Si ;
- Pop Dx ;
- Pop Cx ;
- Mov Ax,TempW ; Get this
- Ret ;
- Trim Endp
-
-
-
- Checksum Proc
- ;-----------------------------------------------------------------------------;
- ; Retruns the checksum of a string (including the asciiz -- as if ) ;
- ; INPUT : ;
- ; DS:SI = address of string ;
- ; OUTPUT: ;
- ; AX = Word Checksum of string (by bytes) -- flags modified ;
- ;-----------------------------------------------------------------------------;
- Push Si ; Save what we use
- Push Bx ;
- Push Cx ;
- ;
- Call Length ; Get the length
- Mov Cx,Ax ; Put it here
- Xor Bx,Bx ;
- Xor Ax,Ax ; This too
- @@: Add Ax,[Bx+Si] ; So add
- Inc Bx ; By one
- Loop @B ; Loop Baxk
- ;
- Pop Cx ;
- Pop Bx ;
- Pop Si ;
- Test Ax,Ax ; Set the flags
- Ret ;
- Checksum Endp
-
-
- Compare Proc
- ;-----------------------------------------------------------------------------;
- ; Compares 2 input string and returns the compare result as follows... ;
- ; If CF reset then the strings were exactly equal. ;
- ; Otherwise AX returns sevral values.. see below ;
- ; INPUT : ;
- ; DS:SI = Address of first string. ;
- ; ES:DI = Address of second string. ;
- ; OUTPUT: ;
- ; If CF=0 AND AX = 0 Then the Strings are Identical. ;
- ; If CF=0 AND AX > 0 Then Str2 = Str1 Upto(AX offset in Str1)... ;
- ; LengthOfStr2 < LengthOfStr1. ;
- ; IF CF=0 AND AX < 0 Then Str1 = Str2 (AX NegativeOffset in Str2) ;
- ; LengthOfStr1 < LengthOfStr2. ;
- ; Note above that strings are equal to a point and AX holds dif. ;
- ; If CF=1 AND AX > 0 Then Str1>Str2 and AX = Offset of Mismatch ;
- ; If CF=1 AND AX < 0 Then Str1<Str2 and AX = NegativeOffset Mismatch ;
- ; Just a note that Negative offset if the numerical negative of the offset ;
- ; for that given number. To find the actual offset, absolute value the num. ;
- ;-----------------------------------------------------------------------------;
- Push Bx ;
- Push Cx ;
- Push Si ;
- Push Di ;
- ;
- Call Length ; Get length of Number 1
- Xchg Ax,Bx ; Flip to save
- XchgSeg Ds,Es ; Exchange the segments
- Call Length ; And get length of string 2
- XchgSeg Ds,Es ; Switch them back
- Xchg Ax,Bx ; LENGTH1 in AX, LENGTH2 in BX
- Cmp Ax,Bx ; Check Ax vs. Bx
- Je sameLength ; The strings are the same length.
- ;
- ;
- sameLength: Mov TempW,Ax ; Save the length that we got
- Mov Cx,Ax ; Put the count for the test here
- Clc ; Clear for fun!
- Repe Cmpsb ; Keep comparing the things
- Je slEqual ; Same length strings are equal
- Pushf ; Save the flags
- Mov Ax,TempW ; Get that saved length
- Sub Ax,Cx ; Which char erred
- Dec Ax ; One more for the offset
- Popf ; Get the flags to see WHICH is bigger
- Jnb str1Bigger ; If not below then 1 is bigger than 2
- Neg Ax ; Send back the negative offset
- str1Bigger: Stc ; Set the carry
- Jmp short compExit; Exit out of here
- slEqual: Clc ; Clear the carry
- Xor Ax,Ax ; Clear AX
- Jmp short compExit; Exit out of here
- ;
- ;
- compExit: Mov TempW,Ax ; Save this
- Lahf ; Save thew flags
- Mov TempB,Ah ; Put this here
- Pop Di ;
- Pop Si ;
- Pop Cx ;
- Pop Bx ;
- Mov Ah,TempB ; Get the flags
- Sahf ; Set the flags
- Mov Ax,TempW ; Get AX Back
- Ret ; Say by bye
- Compare Endp
-
- END