home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter16 / qscan3.asm < prev   
Assembly Source File  |  1997-06-18  |  7KB  |  193 lines

  1. ;  QSCAN3.ASM
  2. ;  David Stafford
  3.  
  4.         COMMENT $
  5.  
  6. How it works
  7. ------------
  8. The idea is to go through the buffer fetching each letter-pair (words
  9. rather than bytes).  The carry flag indicates whether we are
  10. currently in a (text)word or not.  The letter-pair fetched from the
  11. buffer is converted to a 16-bit address by shifting it left one bit
  12. (losing the high bit of the second character) and putting the carry
  13. flag in the low bit.  The high bit of the count register is set to
  14. 1.  Then the count register is added to the byte found at the given
  15. address in a large (64K, naturally) table.  The byte at the given
  16. address will contain a 1 in the high bit if the last character of the
  17. letter-pair is a word-letter (alphanumeric or apostrophe).  This will
  18. set the carry flag since the high bit of the count register is also a
  19. 1. The low bit of the byte found at the given address will be one if
  20. the second character of the previous letter-pair was a word-letter
  21. and the first character of this letter-pair is not a word-letter. It
  22. will also be 1 if the first character of this letter-pair is a
  23. word-letter but the second character is not.  This process is
  24. repeated.  Finally, the carry flag is saved to indicate the final
  25. in-a-word/not-in-a-word status.  The count register is masked to
  26. remove the high bit and the count of words remains in the count
  27. register.
  28.  
  29. Sound complicated?  You're right!  But it's fast!
  30.  
  31. The beauty of this method is that no jumps are required, the
  32. operations are fast, it requires only one table and the process can
  33. be repeated (unrolled) many times.  QSCAN3 can read 256 bytes without
  34. jumping.
  35.  
  36.         COMMEND $
  37.  
  38.                 .model small
  39.                 .code
  40.  
  41. Test1           macro   x,y                     ;9 or 10 bytes
  42. Addr&x:         mov     di,[bp+y]               ;3 or 4 bytes
  43.                 adc     di,di
  44.                 or      ax,si
  45.                 add     al,[di]
  46.                 endm
  47.  
  48. Test2           macro   x,y                     ;7 or 8 bytes
  49. Addr&x:         mov     di,[bp+y]               ;3 or 4 bytes
  50.                 adc     di,di
  51.                 add     ah,[di]
  52.                 endm
  53.  
  54. Scan            =       128                     ;scan 256 bytes at a time
  55.  
  56. Buffer          =       4                       ;parms
  57. BufferLength    =       6
  58. CharFlag        =       8
  59. WordCount       =       10
  60.  
  61.                 public _ScanBuffer
  62. _ScanBuffer     proc near
  63.                 push    bp
  64.                 mov     bp,sp
  65.                 push    si
  66.                 push    di
  67.  
  68.                 xor     cx,cx
  69.                 mov     si,[bp+Buffer]          ;si = text buffer
  70.                 mov     ax,[bp+BufferLength]    ;dx = length in bytes
  71.                 shr     ax,1                    ;dx = length in words
  72.                 jnz     NormalBuf
  73. OneByteBuf:
  74.                 mov     ax,seg WordTable
  75.                 mov     es,ax
  76.  
  77.                 mov     di,[bp+CharFlag]
  78.                 mov     bh,[di]                 ;bh = old CharFlag
  79.                 mov     bl,[si]                 ;bl = character
  80.                 add     bh,'A'-1                ;make bh into character
  81.                 add     bx,bx                   ;prepare to index
  82.                 mov     al,es:[bx]
  83.                 cbw                             ;get hi bit in ah (then bh)
  84.                 shr     al,1                    ;get low bit
  85.                 adc     cx,cx                   ;cx = 0 or 1
  86.                 xchg    ax,bx
  87.                 jmp     CleanUp
  88. NormalBuf:
  89.                 push    bp                      ;(1)
  90.                 pushf                           ;(2)
  91.  
  92.                 cwd                             ;dx = 0
  93.                 mov     cl,Scan
  94.                 div     cx
  95.                 or      dx,dx                   ;remainder?
  96.                 jz      StartAtTheTop           ;nope, do the whole banana
  97.  
  98.                 sub     cx,dx
  99.                 sub     si,cx                   ;adjust buf pointer
  100.                 sub     si,cx
  101.                 inc     ax                      ;adjust for partial read
  102.  
  103. StartAtTheTop:  mov     bx,dx                   ;get index for start...
  104.                 shl     bx,1
  105.                 mov     di,LoopEntry[bx]        ;...address in di
  106.  
  107.                 xchg    dx,ax                   ;dx is the loop counter
  108.                 xor     cx,cx                   ;total word count
  109.  
  110.                 mov     bx,[bp+CharFlag]
  111.                 mov     bl,[bx]                 ;bl = old CharFlag
  112.  
  113.                 mov     bp,seg WordTable
  114.                 mov     ds,bp
  115.  
  116.                 mov     bp,si                   ;scan buffer with bp
  117.                 mov     si,8080h                ;hi bits
  118.                 mov     ax,si                   ;init local word counter
  119.  
  120.                 shr     bl,1                    ;carry = old CharFlag
  121.                 jmp     di
  122.  
  123.                 align   2
  124. Top:            add     bx,bx                   ;restore carry
  125. n               =       0
  126.                 rept    Scan/2
  127.                 Test1   %n,%n*2
  128.                 Test2   %n+1,%n*2+2
  129. n               =       n+2
  130.                 endm
  131. EndCount:
  132.                 sbb     bx,bx                   ;save carry
  133.  
  134. if              Scan ge 128                     ;because al+ah may equal 128!
  135.                 or      ax,si
  136.                 add     al,ah
  137.                 mov     ah,0
  138. else
  139.                 add     al,ah
  140.                 and     ax,7fh                  ;mask
  141. endif
  142.                 add     cx,ax                   ;update word count
  143.                 mov     ax,si
  144.                 add     bp,Scan*2
  145.  
  146.                 dec     dx                      ;any left?
  147.                 jng     Quit
  148.                 jmp     Top
  149.  
  150. Quit:           popf                            ;(2) even or odd buffer?
  151.                 jnc     ItsEven
  152.  
  153.                 clc
  154.                 Test1   Odd,-1
  155.                 sbb     bx,bx                   ;save carry
  156.                 shr     ax,1
  157.                 adc     cx,0
  158. ItsEven:
  159.                 push    ss                      ;restore ds
  160.                 pop     ds
  161.                 pop     bp                      ;(1)
  162. CleanUp:
  163.                 mov     si,[bp+WordCount]
  164.                 add     [si],cx
  165.                 adc     word ptr [si+2],0
  166.  
  167.                 and     bh,1                    ;save only the carry flag
  168.                 mov     si,[bp+CharFlag]
  169.                 mov     [si],bh
  170.  
  171.                 pop     di
  172.                 pop     si
  173.                 pop     bp
  174.                 ret
  175. _ScanBuffer     endp
  176.  
  177.                 .data
  178. Address         macro   X
  179.                 dw      Addr&X
  180.                 endm
  181.  
  182. LoopEntry       label word
  183. n               =       Scan
  184.                 REPT Scan
  185.                 Address %n MOD Scan
  186. n               =       n - 1
  187.                 ENDM
  188.  
  189.                 .fardata WordTable
  190. include         qscan3.inc                      ;built by MAKETAB
  191.                 end
  192.  
  193.