; Jeff Owens

comment |

Here is small routine to scan buffers for a string.  If this seems
trivial, then try to code it before looking at the following logic.
The routine must handle case matching or matching any case, and
allow for matches split across two buffers.  Also, it should be
small and efficient.  If anyone can improve it or do better
then please post.
|

;----------------------------------------------------------------------
; search_block - scan next block of sequential data for string match
;  inputs:  es:bx   =   compare string start (string terminated with zero)
;           es:di   =   compare string current location
;           ds:si   =   buffer current location
;              cx   =   buffer size (remaining byte count)
;              dl   =   case flag  0=(case match)  20h=(match either case)
;           direction flag = CLD state
;
;  output:  registers di,si,cx are updated
;           if cx=0 then no match was found, check if bx=di to determine
;                   if a partial match is in process at buffer end.
;           if cx=non zero, then ds:si points at match end.  The
;                 variable match_si decremented by one = match start.
;                 use -si- and -cx- as returned to continue searching
;                 in current buffer.
;
;  Note:  If a partial match fails and the partial match was split
;         accross two buffers, then extra processing may be needed
;         by the caller to restart the compare in the first buffer.
;
match_si        dw        0
match_cx        dw        0

search_block:                                compare:
        mov     ah,es:[di]                        lodsb
sb_lp1: jcxz    sb_at_buf_end                     dec     cx
        call    compare                           cmp     al,'A'
        jne     sb_lp1                            jb      exit_cmp
        mov     cs:match_si,si                    cmp     al,'Z'
        mov     cs:match_cx,cx                    jbe     al_is_upper
sb_lp2: inc     di                                cmp     al,'a'
        mov     ah,es:[di]                        jb      exit_cmp
        cmp     ah,0                              cmp     al,'z'
        je      sb_total_match                    ja      exit_cmp
        jcxz    sb_at_buf_end                     cmp     al,ah
        call    compare                           je      nc_exit
        je      sb_lp2                            sub     al,dl
        mov     si,cs:match_si                    jmp     exit_cmp
        mov     cx,cs:match_cx                 al_is_upper:
        mov     di,bx                              cmp    al,ah
        jmp     search_block                       je     nc_exit
sb_total_match:                                    add    al,dl
        mov     di,bx                          exit_cmp:
sb_at_buf_end:                                      cmp    al,ah
        ret                                    nc_exit:
                                                     ret

