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

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