Metropoli BBS
VIEWER: lst11-28.asm MODE: TEXT (ASCII)
;
; *** Listing 11-28 ***
;
; Searches a text buffer for a sequence of bytes by checking
; for the sequence with CMPS starting at each byte of the
; buffer that potentially could start the sequence.
;
	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: AX, 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 is taken to mean
;	that the buffer is 64K bytes long.
;
FindSequence:
	cld
	mov	bp,si	;set aside the sequence start
			; offset
	mov	ax,di	;set aside the buffer start offset
	mov	bx,cx	;set aside the sequence length
	sub	dx,cx	;difference between buffer and
			; search sequence lengths
	inc	dx	;# of possible sequence start bytes
			; to check in the buffer
FindSequenceLoop:
	mov	cx,bx	;sequence length
	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 havent' 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:
	mov	si,bp	;point to the start of the search
			; sequence again
	inc	ax	;advance to the next buffer start
			; search location
	mov	di,ax	;point DI to the next buffer start
			; search location
	dec	dx	;count down the remaining bytes to
			; search in the buffer
	jnz	FindSequenceLoop
	sub	di,di	;return 0 pointer indicating that
	mov	es,di	; the sequence was not found
	ret
FindSequenceFound:
	mov	di,ax	;point to the buffer location at
			; which the first occurrence of the
			; sequence was found
	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

[ RETURN TO DIRECTORY ]