home *** CD-ROM | disk | FTP | other *** search
- ;
- ; *** Listing 11-29 ***
- ;
- ; Searches a text buffer for a sequence of bytes by using
- ; REPNZ SCASB to identify bytes in the buffer that
- ; potentially could start the sequence and then checking
- ; only starting at those qualified bytes for a match with
- ; the sequence by way of REPZ CMPS.
- ;
- jmp Skip
- ;
- ; Text buffer that we'll search.
- ;
- TextBuffer label byte
- db 'This is a sample text buffer, suitable '
- db 'for a searching text of any sort... '
- db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 '
- db 'End of text... '
- TEXT_BUFFER_LENGTH equ ($-TextBuffer)
- ;
- ; Sequence of bytes that we'll search for.
- ;
- SearchSequence label byte
- db 'text...'
- SEARCH_SEQUENCE_LENGTH equ ($-SearchSequence)
- ;
- ; Searches a buffer for the first occurrence of a specified
- ; sequence of bytes.
- ;
- ; Input:
- ; CX = length of sequence of bytes to search for
- ; DX = length of buffer to search in
- ; DS:SI = start of sequence of bytes to search for
- ; ES:DI = start of buffer to search
- ;
- ; Output:
- ; ES:DI = pointer to start of first occurrence of
- ; desired sequence of bytes in the buffer, or
- ; 0:0 if the sequence wasn't found
- ;
- ; Registers altered: AL, BX, CX, DX, SI, DI, BP
- ;
- ; Direction flag cleared
- ;
- ; Note: Does not handle search sequences or text buffers
- ; that are longer than 64K bytes or cross segment
- ; boundaries.
- ;
- ; Note: Assumes non-zero length of search sequence (CX > 0),
- ; and search sequence shorter than 64K (CX <= 0ffffh).
- ;
- ; Note: Assumes buffer is longer than search sequence
- ; (DX > CX). Zero length of buffer (DX = 0) is taken
- ; to mean that the buffer is 64K bytes long.
- ;
- FindSequence:
- cld
- lodsb ;get the first byte of the search
- ; sequence, which we'll leave in AL
- ; for faster searching
- mov bp,si ;set aside the sequence start
- ; offset plus one
- dec cx ;we don't need to compare the first
- ; byte of the sequence with CMPS,
- ; since we'll do it with SCAS
- mov bx,cx ;set aside the sequence length
- ; minus 1
- sub dx,cx ;difference between buffer and
- ; search sequence lengths plus 1
- ; (# of possible sequence start
- ; bytes to check in the buffer)
- mov cx,dx ;put buffer search length in CX
- jnz FindSequenceLoop ;start normally if the
- ; buffer isn't 64Kb long
- dec cx ;the buffer is 64K bytes long-we
- ; have to check the first byte
- ; specially since CX = 0 means
- ; "do nothing" to REPNZ SCASB
- scasb ;check the first byte of the buffer
- jz FindSequenceCheck ;it's a match for 1 byte,
- ; at least-check the rest
- FindSequenceLoop:
- repnz scasb ;search for the first byte of the
- ; search sequence
- jnz FindSequenceNotFound
- ;it's not found, so there are no
- ; possible matches
- FindSequenceCheck:
- ;we've got a potential (first byte)
- ; match-check the rest of this
- ; candidate sequence
- push di ;remember the address of the next
- ; byte to check in case it's needed
- mov dx,cx ;set aside the remaining length to
- ; search in the buffer
- mov si,bp ;point to the rest of the search
- ; sequence
- mov cx,bx ;sequence length (minus first byte)
- shr cx,1 ;convert to word for faster search
- jnc FindSequenceWord ;do word search if no odd
- ; byte
- cmpsb ;compare the odd byte
- jnz FindSequenceNoMatch
- ;odd byte doesn't match,
- ; so we haven't found the
- ; search sequence here
- FindSequenceWord:
- jcxz FindSequenceFound
- ;since we're guaranteed to have
- ; a non-zero length, the
- ; sequence must be 1 byte long
- ; and we've already found that
- ; it matched
- repz cmpsw ;check the rest of the sequence a
- ; word at a time for speed
- jz FindSequenceFound ;it's a match
- FindSequenceNoMatch:
- pop di ;get back the pointer to the next
- ; byte to check
- mov cx,dx ;get back the remaining length to
- ; search in the buffer
- and cx,cx ;see if there's anything left to
- ; check
- jnz FindSequenceLoop ;yes-check next byte
- FindSequenceNotFound:
- sub di,di ;return 0 pointer indicating that
- mov es,di ; the sequence was not found
- ret
- FindSequenceFound:
- pop di ;point to the buffer location at
- dec di ; which the first occurrence of the
- ; sequence was found (remember that
- ; earlier we pushed the address of
- ; the byte after the potential
- ; sequence start)
- ret
- ;
- Skip:
- call ZTimerOn
- mov si,offset SearchSequence
- ;point to search sequence
- mov cx,SEARCH_SEQUENCE_LENGTH
- ;length of search sequence
- mov di,seg TextBuffer
- mov es,di
- mov di,offset TextBuffer
- ;point to buffer to search
- mov dx,TEXT_BUFFER_LENGTH
- ;length of buffer to search
- call FindSequence ;search for the sequence
- call ZTimerOff