;; BuildCVTable builds the characteristic vector table for a search pattern
;; that is up to 32 characters in length. No error checking is performed to
;; verify that the pattern length is greater than 0 and less than or equal
;; to 32.
;;
;; Call with: DS:SI -> Pattern
;;            ES:DI -> Characteristic vector table
;;               CX  = Pattern length
;;
;; Note: The characteristic vector table should contain 256 double words.

BuildCVTable    proc    near
                push    cx                      ;Save CX
                push    di                      ;Save DI
                cld                             ;Clear direction flag
                mov     cx,512                  ;Initialize counter
                xor     ax,ax                   ;Initialize the CVT so
                rep     stosw                   ;it contains all zeroes
                pop     di                      ;Restore DI
                pop     cx                      ;Restore CX

                mov     dx,8000h                ;Set DX:AX to 80000000h
                xor     ax,ax

BCVT1:          xor     bh,bh                   ;Initialize BH to 0
                mov     bl,[si]                 ;Get the next character
                inc     si                      ;Increment pointer
                shl     bx,1                    ;Multiply BX by 4 to compute
                shl     bx,1                    ;an index into the CVT
                or      es:[di+bx],ax           ;Set the bit that corresponds
                or      es:[di+bx+2],dx         ;to this position in the CVT
                shr     dx,1                    ;Shift DX:AX right one bit
                rcr     ax,1
                loop    BCVT1                   ;Loop until done
                ret                             ;Return to caller
BuildCVTable    endp

;; FastSearch uses the Shift-AND algorithm described by Manber and Wu
;; in the November 1992 issue of Byte magazine to search a text buffer
;; for an exact pattern match. No error checking is performed to verify
;; that the pattern length is valid, or that the length of the text
;; buffer equals or exceeds the pattern length.
;;
;; Call with: DS:SI -> Text to be searched
;;            ES:DI -> Characteristic vector table
;;               CX  = Pattern length
;;               BX  = Text length
;;
;; Returns:   Carry clear if match found, carry set if not

FastSearch      proc    near
                mov     dx,8000h                ;Set DX:AX to 80000000h
                xor     ax,ax
                dec     cx                      ;Decrement pattern length
FS1:            shr     dx,1                    ;Shift DX:AX right n-1 times,
                rcr     ax,1                    ;where n equals the pattern
                loop    FS1                     ;length
                push    dx                      ;Save DX:AX on the stack
                push    ax
                mov     bp,sp                   ;Copy SP to BP

                xor     dx,dx                   ;Set DX:AX to 0
                xor     ax,ax
                mov     cx,bx                   ;CX = Text length

FS2:            xor     bh,bh                   ;Initialize BH to 0
                mov     bl,[si]                 ;Get the next character
                inc     si                      ;Increment pointer
                shl     bx,1                    ;Multiply BX by 4 to compute
                shl     bx,1                    ;an index into the CVT

                shr     dx,1                    ;Shift DX:AX right one bit
                rcr     ax,1
                or      dx,8000h                ;Set the high bit of DX
                and     ax,es:[di+bx]           ;AND DX:AX with the vector
                and     dx,es:[di+bx+2]         ;for this character

                push    ax                      ;Save DX:AX
                push    dx
                and     ax,[bp]                 ;AND DX:AX with the value
                and     dx,[bp+2]               ;saved on the stack at the
                or      ax,ax                   ;beginning of the routine
                jnz     FSExit
                or      dx,dx                   ;Match found if DX:AX is
                jnz     FSExit                  ;not equal to 0
                pop     dx                      ;Restore DX:AX
                pop     ax
                loop    FS2                     ;Loop until done

                add     sp,4                    ;Clear the stack
                stc                             ;Set the carry flag
                ret                             ;Return to caller

FSExit:         add     sp,8                    ;Clear the stack
                clc                             ;Clear the carry flag
                ret                             ;Return to caller
FastSearch      endp

*****

