home *** CD-ROM | disk | FTP | other *** search
- ;
- ; *** Listing 14-16 ***
- ;
- ; Demonstrates the use of a jump table to branch into
- ; in-line code consisting of repeated code blocks of
- ; varying lengths. Branches out of the in-line code with
- ; 1-byte displacements at both ends of the in-line code,
- ; for improved speed.
- ;
- ; Searches up to N bytes of a zero- terminated string for
- ; a character.
- ;
- jmp Skip
- TestString label byte
- db 'This is a string containing the letter '
- db 'z but not containing capital q', 0
- ;
- ; Searches a zero-terminated string for a character.
- ; Searches until a match is found, the terminating zero
- ; is found, or the specified number of characters has been
- ; checked.
- ;
- ; Input:
- ; AL = character to search for
- ; BX = maximum # of characters to search. Must be
- ; less than or equal to MAX_SEARCH_LENGTH
- ; DS:SI = string to search
- ;
- ; Output:
- ; SI = pointer to character, or 0 if character not
- ; found
- ;
- ; Registers altered: AX, BX, SI
- ;
- ; Direction flag cleared
- ;
- ; Note: Don't pass a string starting at offset 0, since a
- ; match there couldn't be distinguished from a failure
- ; to match.
- ;
- MAX_SEARCH_LENGTH equ 80 ;longest supported search
- ; length
- ;
- ; Macro to create SearchTable entries.
- ;
- MAKE_CHECK_CHAR_LABEL macro NUMBER
- dw CheckChar&NUMBER&
- endm
- ;
- ; Macro to create in-line code to search 1 character.
- ; Gives the code block a unique label according to NUMBER.
- ; Each conditional branch uses the shortest possible jump
- ; sequence to reach NoMatch and MatchFound.
- ;
- CHECK_CHAR macro NUMBER
- local CheckMatch, Continue
- CheckChar&NUMBER&:
- lodsb ;get the character
- and al,al ;done if terminating zero
- ;
- ; Assemble a single conditional jump if it'll reach, or
- ; a conditional jump around an unconditional jump if the
- ; 1-byte displacement of a conditional jump won't reach.
- ;
- if ($+2-NoMatch) le 128
- jz NoMatch
- else
- jnz CheckMatch
- jmp NoMatch
- endif
- CheckMatch:
- cmp ah,al ;done if matches search character
- ;
- ; Again, assemble shortest possible jump sequence.
- ;
- if ($+2-MatchFound) le 128
- jz MatchFound
- else
- jnz Continue
- jmp MatchFound
- endif
- Continue:
- endm
- ;
- ; Macro to create in-line code to search 1 character.
- ; Gives the code block a unique label according to NUMBER.
- ; All branches use a 1-byte displacement to branch to
- ; NoMatch2 and MatchFound2.
- ;
- CHECK_CHAR2 macro NUMBER
- CheckChar&NUMBER&:
- lodsb ;get the character
- and al,al ;done if terminating zero
- jz NoMatch2
- cmp ah,al ;done if matches search character
- jz MatchFound2
- endm
- ;
- ; Table of in-line code entry points for maximum search
- ; lengths of 0 through 80.
- ;
- SearchTable label word
- dw NoMatch ;we never match on a
- ; maximum length of 0
- BLOCK_NUMBER=MAX_SEARCH_LENGTH-1
- rept MAX_SEARCH_LENGTH
- MAKE_CHECK_CHAR_LABEL %BLOCK_NUMBER
- BLOCK_NUMBER=BLOCK_NUMBER-1
- endm
- ;
- SearchNBytes proc near
- mov ah,al ;we'll need AL for LODSB
- cmp bx,MAX_SEARCH_LENGTH
- ja NoMatch ;if the maximum length's
- ; too long for the in-line
- ; code, return a no-match
- ; status
- shl bx,1 ;*2 to look up in word-sized
- ; table
- jmp [SearchTable+bx] ;branch into the in-line
- ; code to do the search
- ;
- ; No match was found.
- ;
- NoMatch:
- sub si,si ;return no-match status
- ret
- ;
- ; A match was found.
- ;
- MatchFound:
- dec si ;point back to matching
- ; location
- ret
- ;
- ; This is the in-line code that actually does the search.
- ; Each repetition is uniquely labelled, with labels
- ; CheckChar0 through CheckChar79.
- ;
- BLOCK_NUMBER=0
- ;
- ; These in-line code blocks use 1-byte displacements
- ; whenever possible to branch backward; otherwise 2-byte
- ; displacements are used to branch backwards, with
- ; conditional jumps around unconditional jumps.
- ;
- rept MAX_SEARCH_LENGTH-14
- CHECK_CHAR %BLOCK_NUMBER
- BLOCK_NUMBER=BLOCK_NUMBER+1
- endm
- ;
- ; These in-line code blocks use 1-byte displacements to
- ; branch forward.
- ;
- rept 14
- CHECK_CHAR2 %BLOCK_NUMBER
- BLOCK_NUMBER=BLOCK_NUMBER+1
- endm
- ;
- ; If we make it here, we haven't found the character.
- ;
- NoMatch2:
- sub si,si ;return no-match status
- ret
- ;
- ; A match was found.
- ;
- MatchFound2:
- dec si ;point back to matching
- ; location
- ret
- SearchNBytes endp
- ;
- Skip:
- call ZTimerOn
- mov al,'Q'
- mov bx,20 ;search up to the
- mov si,offset TestString ; first 20 bytes of
- call SearchNBytes ; TestString for 'Q'
- mov al,'z'
- mov bx,80 ;search up to the
- mov si,offset TestString ; first 80 bytes of
- call SearchNBytes ; TestString for 'z'
- mov al,'a'
- mov bx,10 ;search up to the
- mov si,offset TestString ; first 10 bytes of
- call SearchNBytes ; TestString for 'a'
- call ZTimerOff