home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / zendisk2.zip / LST14-16.ASM < prev    next >
Assembly Source File  |  1990-02-15  |  5KB  |  189 lines

  1. ;
  2. ; *** Listing 14-16 ***
  3. ;
  4. ; Demonstrates the use of a jump table to branch into
  5. ; in-line code consisting of repeated code blocks of
  6. ; varying lengths. Branches out of the in-line code with
  7. ; 1-byte displacements at both ends of the in-line code,
  8. ; for improved speed.
  9. ;
  10. ; Searches up to N bytes of a zero- terminated string for
  11. ; a character.
  12. ;
  13.     jmp    Skip
  14. TestString    label    byte
  15.     db    'This is a string containing the letter '
  16.     db    'z but not containing capital q', 0
  17. ;
  18. ; Searches a zero-terminated string for a character.
  19. ; Searches until a match is found, the terminating zero
  20. ; is found, or the specified number of characters has been
  21. ; checked.
  22. ;
  23. ; Input:
  24. ;    AL = character to search for
  25. ;    BX = maximum # of characters to search. Must be
  26. ;        less than or equal to MAX_SEARCH_LENGTH
  27. ;    DS:SI = string to search
  28. ;
  29. ; Output:
  30. ;    SI = pointer to character, or 0 if character not
  31. ;        found
  32. ;
  33. ; Registers altered: AX, BX, SI
  34. ;
  35. ; Direction flag cleared
  36. ;
  37. ; Note: Don't pass a string starting at offset 0, since a
  38. ;    match there couldn't be distinguished from a failure
  39. ;    to match.
  40. ;
  41. MAX_SEARCH_LENGTH equ    80    ;longest supported search
  42.                 ; length
  43. ;
  44. ; Macro to create SearchTable entries.
  45. ;
  46. MAKE_CHECK_CHAR_LABEL    macro    NUMBER
  47.     dw    CheckChar&NUMBER&
  48.     endm
  49. ;
  50. ; Macro to create in-line code to search 1 character.
  51. ; Gives the code block a unique label according to NUMBER.
  52. ; Each conditional branch uses the shortest possible jump
  53. ; sequence to reach NoMatch and MatchFound.
  54. ;
  55. CHECK_CHAR    macro    NUMBER
  56.     local    CheckMatch, Continue
  57. CheckChar&NUMBER&:
  58.     lodsb        ;get the character
  59.     and    al,al    ;done if terminating zero
  60. ;
  61. ; Assemble a single conditional jump if it'll reach, or
  62. ; a conditional jump around an unconditional jump if the
  63. ; 1-byte displacement of a conditional jump won't reach.
  64. ;
  65. if ($+2-NoMatch) le 128
  66.     jz    NoMatch
  67. else
  68.     jnz    CheckMatch
  69.     jmp    NoMatch
  70. endif
  71. CheckMatch:
  72.     cmp    ah,al    ;done if matches search character
  73. ;
  74. ; Again, assemble shortest possible jump sequence.
  75. ;
  76. if ($+2-MatchFound) le 128
  77.     jz    MatchFound
  78. else
  79.     jnz    Continue
  80.     jmp    MatchFound
  81. endif
  82. Continue:
  83.     endm
  84. ;
  85. ; Macro to create in-line code to search 1 character.
  86. ; Gives the code block a unique label according to NUMBER.
  87. ; All branches use a 1-byte displacement to branch to
  88. ; NoMatch2 and MatchFound2.
  89. ;
  90. CHECK_CHAR2    macro    NUMBER
  91. CheckChar&NUMBER&:
  92.     lodsb        ;get the character
  93.     and    al,al    ;done if terminating zero
  94.     jz    NoMatch2
  95.     cmp    ah,al    ;done if matches search character
  96.     jz    MatchFound2
  97.     endm
  98. ;
  99. ; Table of in-line code entry points for maximum search
  100. ; lengths of 0 through 80.
  101. ;
  102. SearchTable    label    word
  103.     dw    NoMatch        ;we never match on a
  104.                 ; maximum length of 0
  105. BLOCK_NUMBER=MAX_SEARCH_LENGTH-1
  106.     rept    MAX_SEARCH_LENGTH
  107.     MAKE_CHECK_CHAR_LABEL    %BLOCK_NUMBER
  108. BLOCK_NUMBER=BLOCK_NUMBER-1
  109.     endm
  110. ;
  111. SearchNBytes    proc    near
  112.     mov    ah,al        ;we'll need AL for LODSB
  113.     cmp    bx,MAX_SEARCH_LENGTH
  114.     ja    NoMatch        ;if the maximum length's
  115.                 ; too long for the in-line
  116.                 ; code, return a no-match
  117.                 ; status
  118.     shl    bx,1        ;*2 to look up in word-sized
  119.                 ; table
  120.     jmp    [SearchTable+bx] ;branch into the in-line
  121.                 ; code to do the search
  122. ;
  123. ; No match was found.
  124. ;
  125. NoMatch:
  126.     sub    si,si        ;return no-match status
  127.     ret
  128. ;
  129. ; A match was found.
  130. ;
  131. MatchFound:
  132.     dec    si        ;point back to matching
  133.                 ; location
  134.     ret
  135. ;
  136. ; This is the in-line code that actually does the search.
  137. ; Each repetition is uniquely labelled, with labels
  138. ; CheckChar0 through CheckChar79.
  139. ;
  140. BLOCK_NUMBER=0
  141. ;
  142. ; These in-line code blocks use 1-byte displacements
  143. ; whenever possible to branch backward; otherwise 2-byte
  144. ; displacements are used to branch backwards, with
  145. ; conditional jumps around unconditional jumps.
  146. ;
  147.     rept    MAX_SEARCH_LENGTH-14
  148.     CHECK_CHAR    %BLOCK_NUMBER
  149. BLOCK_NUMBER=BLOCK_NUMBER+1
  150.     endm
  151. ;
  152. ; These in-line code blocks use 1-byte displacements to
  153. ; branch forward.
  154. ;
  155.     rept    14
  156.     CHECK_CHAR2    %BLOCK_NUMBER
  157. BLOCK_NUMBER=BLOCK_NUMBER+1
  158.     endm
  159. ;
  160. ; If we make it here, we haven't found the character.
  161. ;
  162. NoMatch2:
  163.     sub    si,si    ;return no-match status
  164.     ret
  165. ;
  166. ; A match was found.
  167. ;
  168. MatchFound2:
  169.     dec    si        ;point back to matching
  170.                 ; location
  171.     ret
  172. SearchNBytes    endp
  173. ;
  174. Skip:
  175.     call    ZTimerOn
  176.     mov    al,'Q'
  177.     mov    bx,20            ;search up to the
  178.     mov    si,offset TestString    ; first 20 bytes of
  179.     call    SearchNBytes        ; TestString for 'Q'
  180.     mov    al,'z'
  181.     mov    bx,80            ;search up to the
  182.     mov    si,offset TestString    ; first 80 bytes of
  183.     call    SearchNBytes        ; TestString for 'z'
  184.     mov    al,'a'
  185.     mov    bx,10            ;search up to the
  186.     mov    si,offset TestString    ; first 10 bytes of
  187.     call    SearchNBytes        ; TestString for 'a'
  188.     call    ZTimerOff
  189.