gvmat32.asm
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:27k
源码类别:

通讯编程

开发平台:

Visual C++

  1. ; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
  2. ; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
  3. ; File written by Gilles Vollant, by modifiying the longest_match
  4. ;  from Jean-loup Gailly in deflate.c
  5. ;
  6. ;         http://www.zlib.net
  7. ;         http://www.winimage.com/zLibDll
  8. ;         http://www.muppetlabs.com/~breadbox/software/assembly.html
  9. ;
  10. ; For Visual C++ 4.x and higher and ML 6.x and higher
  11. ;   ml.exe is in directory MASM611C of Win95 DDK
  12. ;   ml.exe is also distributed in http://www.masm32.com/masmdl.htm
  13. ;    and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/
  14. ;
  15. ; this file contain two implementation of longest_match
  16. ;
  17. ;  longest_match_7fff : written 1996 by Gilles Vollant optimized for 
  18. ;            first Pentium. Assume s->w_mask == 0x7fff
  19. ;  longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro
  20. ;
  21. ;  for using an seembly version of longest_match, you need define ASMV in project
  22. ;  There is two way in using gvmat32.asm
  23. ;
  24. ;  A) Suggested method
  25. ;    if you want include both longest_match_7fff and longest_match_686
  26. ;    compile the asm file running
  27. ;           ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm
  28. ;    and include gvmat32c.c in your project
  29. ;    if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,
  30. ;        longest_match_7fff will be used
  31. ;    if you have a more modern CPU (Pentium Pro, II and higher)
  32. ;        longest_match_686 will be used
  33. ;    on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,
  34. ;        but this is not a sitation you'll find often
  35. ;
  36. ;  B) Alternative
  37. ;    if you are not interresed in old cpu performance and want the smaller
  38. ;       binaries possible
  39. ;
  40. ;    compile the asm file running
  41. ;           ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm
  42. ;    and do not include gvmat32c.c in your project (ou define also 
  43. ;              NOOLDPENTIUMCODE)
  44. ;
  45. ; note : as I known, longest_match_686 is very faster than longest_match_7fff
  46. ;        on pentium Pro/II/III, faster (but less) in P4, but it seem
  47. ;        longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8
  48. ;
  49. ; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
  50. ;uInt longest_match_7fff(s, cur_match)
  51. ;    deflate_state *s;
  52. ;    IPos cur_match;                             /* current match */
  53.     NbStack         equ     76
  54.     cur_match       equ     dword ptr[esp+NbStack-0]
  55.     str_s           equ     dword ptr[esp+NbStack-4]
  56. ; 5 dword on top (ret,ebp,esi,edi,ebx)
  57.     adrret          equ     dword ptr[esp+NbStack-8]
  58.     pushebp         equ     dword ptr[esp+NbStack-12]
  59.     pushedi         equ     dword ptr[esp+NbStack-16]
  60.     pushesi         equ     dword ptr[esp+NbStack-20]
  61.     pushebx         equ     dword ptr[esp+NbStack-24]
  62.     chain_length    equ     dword ptr [esp+NbStack-28]
  63.     limit           equ     dword ptr [esp+NbStack-32]
  64.     best_len        equ     dword ptr [esp+NbStack-36]
  65.     window          equ     dword ptr [esp+NbStack-40]
  66.     prev            equ     dword ptr [esp+NbStack-44]
  67.     scan_start      equ      word ptr [esp+NbStack-48]
  68.     wmask           equ     dword ptr [esp+NbStack-52]
  69.     match_start_ptr equ     dword ptr [esp+NbStack-56]
  70.     nice_match      equ     dword ptr [esp+NbStack-60]
  71.     scan            equ     dword ptr [esp+NbStack-64]
  72.     windowlen       equ     dword ptr [esp+NbStack-68]
  73.     match_start     equ     dword ptr [esp+NbStack-72]
  74.     strend          equ     dword ptr [esp+NbStack-76]
  75.     NbStackAdd      equ     (NbStack-24)
  76.     .386p
  77.     name    gvmatch
  78.     .MODEL  FLAT
  79. ;  all the +zlib1222add offsets are due to the addition of fields
  80. ;  in zlib in the deflate_state structure since the asm code was first written
  81. ;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
  82. ;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
  83. ;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
  84.     zlib1222add         equ     8
  85. ;  Note : these value are good with a 8 bytes boundary pack structure
  86.     dep_chain_length    equ     74h+zlib1222add
  87.     dep_window          equ     30h+zlib1222add
  88.     dep_strstart        equ     64h+zlib1222add
  89.     dep_prev_length     equ     70h+zlib1222add
  90.     dep_nice_match      equ     88h+zlib1222add
  91.     dep_w_size          equ     24h+zlib1222add
  92.     dep_prev            equ     38h+zlib1222add
  93.     dep_w_mask          equ     2ch+zlib1222add
  94.     dep_good_match      equ     84h+zlib1222add
  95.     dep_match_start     equ     68h+zlib1222add
  96.     dep_lookahead       equ     6ch+zlib1222add
  97. _TEXT                   segment
  98. IFDEF NOUNDERLINE
  99.    IFDEF NOOLDPENTIUMCODE
  100.             public  longest_match
  101.             public  match_init
  102.    ELSE            
  103.             public  longest_match_7fff
  104.             public  cpudetect32
  105.             public  longest_match_686
  106.    ENDIF
  107. ELSE
  108.    IFDEF NOOLDPENTIUMCODE
  109.             public  _longest_match
  110.             public  _match_init
  111.    ELSE
  112.             public  _longest_match_7fff
  113.             public  _cpudetect32
  114.             public  _longest_match_686
  115.    ENDIF
  116. ENDIF
  117.     MAX_MATCH           equ     258
  118.     MIN_MATCH           equ     3
  119.     MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
  120. IFNDEF NOOLDPENTIUMCODE
  121. IFDEF NOUNDERLINE
  122. longest_match_7fff   proc near
  123. ELSE
  124. _longest_match_7fff  proc near
  125. ENDIF
  126.     mov     edx,[esp+4]
  127.     push    ebp
  128.     push    edi
  129.     push    esi
  130.     push    ebx
  131.     sub     esp,NbStackAdd
  132. ; initialize or check the variables used in match.asm.
  133.     mov     ebp,edx
  134. ; chain_length = s->max_chain_length
  135. ; if (prev_length>=good_match) chain_length >>= 2
  136.     mov     edx,[ebp+dep_chain_length]
  137.     mov     ebx,[ebp+dep_prev_length]
  138.     cmp     [ebp+dep_good_match],ebx
  139.     ja      noshr
  140.     shr     edx,2
  141. noshr:
  142. ; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
  143.     inc     edx
  144.     mov     edi,[ebp+dep_nice_match]
  145.     mov     chain_length,edx
  146.     mov     eax,[ebp+dep_lookahead]
  147.     cmp     eax,edi
  148. ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
  149.     jae     nolookaheadnicematch
  150.     mov     edi,eax
  151. nolookaheadnicematch:
  152. ; best_len = s->prev_length
  153.     mov     best_len,ebx
  154. ; window = s->window
  155.     mov     esi,[ebp+dep_window]
  156.     mov     ecx,[ebp+dep_strstart]
  157.     mov     window,esi
  158.     mov     nice_match,edi
  159. ; scan = window + strstart
  160.     add     esi,ecx
  161.     mov     scan,esi
  162. ; dx = *window
  163.     mov     dx,word ptr [esi]
  164. ; bx = *(window+best_len-1)
  165.     mov     bx,word ptr [esi+ebx-1]
  166.     add     esi,MAX_MATCH-1
  167. ; scan_start = *scan
  168.     mov     scan_start,dx
  169. ; strend = scan + MAX_MATCH-1
  170.     mov     strend,esi
  171. ; bx = scan_end = *(window+best_len-1)
  172. ;    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
  173. ;        s->strstart - (IPos)MAX_DIST(s) : NIL;
  174.     mov     esi,[ebp+dep_w_size]
  175.     sub     esi,MIN_LOOKAHEAD
  176. ; here esi = MAX_DIST(s)
  177.     sub     ecx,esi
  178.     ja      nodist
  179.     xor     ecx,ecx
  180. nodist:
  181.     mov     limit,ecx
  182. ; prev = s->prev
  183.     mov     edx,[ebp+dep_prev]
  184.     mov     prev,edx
  185. ;
  186.     mov     edx,dword ptr [ebp+dep_match_start]
  187.     mov     bp,scan_start
  188.     mov     eax,cur_match
  189.     mov     match_start,edx
  190.     mov     edx,window
  191.     mov     edi,edx
  192.     add     edi,best_len
  193.     mov     esi,prev
  194.     dec     edi
  195. ; windowlen = window + best_len -1
  196.     mov     windowlen,edi
  197.     jmp     beginloop2
  198.     align   4
  199. ; here, in the loop
  200. ;       eax = ax = cur_match
  201. ;       ecx = limit
  202. ;        bx = scan_end
  203. ;        bp = scan_start
  204. ;       edi = windowlen (window + best_len -1)
  205. ;       esi = prev
  206. ;// here; chain_length <=16
  207. normalbeg0add16:
  208.     add     chain_length,16
  209.     jz      exitloop
  210. normalbeg0:
  211.     cmp     word ptr[edi+eax],bx
  212.     je      normalbeg2noroll
  213. rcontlabnoroll:
  214. ; cur_match = prev[cur_match & wmask]
  215.     and     eax,7fffh
  216.     mov     ax,word ptr[esi+eax*2]
  217. ; if cur_match > limit, go to exitloop
  218.     cmp     ecx,eax
  219.     jnb     exitloop
  220. ; if --chain_length != 0, go to exitloop
  221.     dec     chain_length
  222.     jnz     normalbeg0
  223.     jmp     exitloop
  224. normalbeg2noroll:
  225. ; if (scan_start==*(cur_match+window)) goto normalbeg2
  226.     cmp     bp,word ptr[edx+eax]
  227.     jne     rcontlabnoroll
  228.     jmp     normalbeg2
  229. contloop3:
  230.     mov     edi,windowlen
  231. ; cur_match = prev[cur_match & wmask]
  232.     and     eax,7fffh
  233.     mov     ax,word ptr[esi+eax*2]
  234. ; if cur_match > limit, go to exitloop
  235.     cmp     ecx,eax
  236. jnbexitloopshort1:
  237.     jnb     exitloop
  238. ; if --chain_length != 0, go to exitloop
  239. ; begin the main loop
  240. beginloop2:
  241.     sub     chain_length,16+1
  242. ; if chain_length <=16, don't use the unrolled loop
  243.     jna     normalbeg0add16
  244. do16:
  245.     cmp     word ptr[edi+eax],bx
  246.     je      normalbeg2dc0
  247. maccn   MACRO   lab
  248.     and     eax,7fffh
  249.     mov     ax,word ptr[esi+eax*2]
  250.     cmp     ecx,eax
  251.     jnb     exitloop
  252.     cmp     word ptr[edi+eax],bx
  253.     je      lab
  254.     ENDM
  255. rcontloop0:
  256.     maccn   normalbeg2dc1
  257. rcontloop1:
  258.     maccn   normalbeg2dc2
  259. rcontloop2:
  260.     maccn   normalbeg2dc3
  261. rcontloop3:
  262.     maccn   normalbeg2dc4
  263. rcontloop4:
  264.     maccn   normalbeg2dc5
  265. rcontloop5:
  266.     maccn   normalbeg2dc6
  267. rcontloop6:
  268.     maccn   normalbeg2dc7
  269. rcontloop7:
  270.     maccn   normalbeg2dc8
  271. rcontloop8:
  272.     maccn   normalbeg2dc9
  273. rcontloop9:
  274.     maccn   normalbeg2dc10
  275. rcontloop10:
  276.     maccn   short normalbeg2dc11
  277. rcontloop11:
  278.     maccn   short normalbeg2dc12
  279. rcontloop12:
  280.     maccn   short normalbeg2dc13
  281. rcontloop13:
  282.     maccn   short normalbeg2dc14
  283. rcontloop14:
  284.     maccn   short normalbeg2dc15
  285. rcontloop15:
  286.     and     eax,7fffh
  287.     mov     ax,word ptr[esi+eax*2]
  288.     cmp     ecx,eax
  289.     jnb     exitloop
  290.     sub     chain_length,16
  291.     ja      do16
  292.     jmp     normalbeg0add16
  293. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  294. normbeg MACRO   rcontlab,valsub
  295. ; if we are here, we know that *(match+best_len-1) == scan_end
  296.     cmp     bp,word ptr[edx+eax]
  297. ; if (match != scan_start) goto rcontlab
  298.     jne     rcontlab
  299. ; calculate the good chain_length, and we'll compare scan and match string
  300.     add     chain_length,16-valsub
  301.     jmp     iseq
  302.     ENDM
  303. normalbeg2dc11:
  304.     normbeg rcontloop11,11
  305. normalbeg2dc12:
  306.     normbeg short rcontloop12,12
  307. normalbeg2dc13:
  308.     normbeg short rcontloop13,13
  309. normalbeg2dc14:
  310.     normbeg short rcontloop14,14
  311. normalbeg2dc15:
  312.     normbeg short rcontloop15,15
  313. normalbeg2dc10:
  314.     normbeg rcontloop10,10
  315. normalbeg2dc9:
  316.     normbeg rcontloop9,9
  317. normalbeg2dc8:
  318.     normbeg rcontloop8,8
  319. normalbeg2dc7:
  320.     normbeg rcontloop7,7
  321. normalbeg2dc6:
  322.     normbeg rcontloop6,6
  323. normalbeg2dc5:
  324.     normbeg rcontloop5,5
  325. normalbeg2dc4:
  326.     normbeg rcontloop4,4
  327. normalbeg2dc3:
  328.     normbeg rcontloop3,3
  329. normalbeg2dc2:
  330.     normbeg rcontloop2,2
  331. normalbeg2dc1:
  332.     normbeg rcontloop1,1
  333. normalbeg2dc0:
  334.     normbeg rcontloop0,0
  335. ; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
  336. normalbeg2:
  337.     mov     edi,window
  338.     cmp     bp,word ptr[edi+eax]
  339.     jne     contloop3                   ; if *(ushf*)match != scan_start, continue
  340. iseq:
  341. ; if we are here, we know that *(match+best_len-1) == scan_end
  342. ; and (match == scan_start)
  343.     mov     edi,edx
  344.     mov     esi,scan                    ; esi = scan
  345.     add     edi,eax                     ; edi = window + cur_match = match
  346.     mov     edx,[esi+3]                 ; compare manually dword at match+3
  347.     xor     edx,[edi+3]                 ; and scan +3
  348.     jz      begincompare                ; if equal, go to long compare
  349. ; we will determine the unmatch byte and calculate len (in esi)
  350.     or      dl,dl
  351.     je      eq1rr
  352.     mov     esi,3
  353.     jmp     trfinval
  354. eq1rr:
  355.     or      dx,dx
  356.     je      eq1
  357.     mov     esi,4
  358.     jmp     trfinval
  359. eq1:
  360.     and     edx,0ffffffh
  361.     jz      eq11
  362.     mov     esi,5
  363.     jmp     trfinval
  364. eq11:
  365.     mov     esi,6
  366.     jmp     trfinval
  367. begincompare:
  368.     ; here we now scan and match begin same
  369.     add     edi,6
  370.     add     esi,6
  371.     mov     ecx,(MAX_MATCH-(2+4))/4     ; scan for at most MAX_MATCH bytes
  372.     repe    cmpsd                       ; loop until mismatch
  373.     je      trfin                       ; go to trfin if not unmatch
  374. ; we determine the unmatch byte
  375.     sub     esi,4
  376.     mov     edx,[edi-4]
  377.     xor     edx,[esi]
  378.     or      dl,dl
  379.     jnz     trfin
  380.     inc     esi
  381.     or      dx,dx
  382.     jnz     trfin
  383.     inc     esi
  384.     and     edx,0ffffffh
  385.     jnz     trfin
  386.     inc     esi
  387. trfin:
  388.     sub     esi,scan          ; esi = len
  389. trfinval:
  390. ; here we have finised compare, and esi contain len of equal string
  391.     cmp     esi,best_len        ; if len > best_len, go newbestlen
  392.     ja      short newbestlen
  393. ; now we restore edx, ecx and esi, for the big loop
  394.     mov     esi,prev
  395.     mov     ecx,limit
  396.     mov     edx,window
  397.     jmp     contloop3
  398. newbestlen:
  399.     mov     best_len,esi        ; len become best_len
  400.     mov     match_start,eax     ; save new position as match_start
  401.     cmp     esi,nice_match      ; if best_len >= nice_match, exit
  402.     jae     exitloop
  403.     mov     ecx,scan
  404.     mov     edx,window          ; restore edx=window
  405.     add     ecx,esi
  406.     add     esi,edx
  407.     dec     esi
  408.     mov     windowlen,esi       ; windowlen = window + best_len-1
  409.     mov     bx,[ecx-1]          ; bx = *(scan+best_len-1) = scan_end
  410. ; now we restore ecx and esi, for the big loop :
  411.     mov     esi,prev
  412.     mov     ecx,limit
  413.     jmp     contloop3
  414. exitloop:
  415. ; exit : s->match_start=match_start
  416.     mov     ebx,match_start
  417.     mov     ebp,str_s
  418.     mov     ecx,best_len
  419.     mov     dword ptr [ebp+dep_match_start],ebx
  420.     mov     eax,dword ptr [ebp+dep_lookahead]
  421.     cmp     ecx,eax
  422.     ja      minexlo
  423.     mov     eax,ecx
  424. minexlo:
  425. ; return min(best_len,s->lookahead)
  426. ; restore stack and register ebx,esi,edi,ebp
  427.     add     esp,NbStackAdd
  428.     pop     ebx
  429.     pop     esi
  430.     pop     edi
  431.     pop     ebp
  432.     ret
  433. InfoAuthor:
  434. ; please don't remove this string !
  435. ; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
  436.     db     0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
  437. IFDEF NOUNDERLINE
  438. longest_match_7fff   endp
  439. ELSE
  440. _longest_match_7fff  endp
  441. ENDIF
  442. IFDEF NOUNDERLINE
  443. cpudetect32     proc near
  444. ELSE
  445. _cpudetect32    proc near
  446. ENDIF
  447.     push    ebx
  448.     pushfd                  ; push original EFLAGS
  449.     pop     eax             ; get original EFLAGS
  450.     mov     ecx, eax        ; save original EFLAGS
  451.     xor     eax, 40000h     ; flip AC bit in EFLAGS
  452.     push    eax             ; save new EFLAGS value on stack
  453.     popfd                   ; replace current EFLAGS value
  454.     pushfd                  ; get new EFLAGS
  455.     pop     eax             ; store new EFLAGS in EAX
  456.     xor     eax, ecx        ; can抰 toggle AC bit, processor=80386
  457.     jz      end_cpu_is_386  ; jump if 80386 processor
  458.     push    ecx
  459.     popfd                   ; restore AC bit in EFLAGS first
  460.     pushfd
  461.     pushfd
  462.     pop     ecx
  463.     mov     eax, ecx        ; get original EFLAGS
  464.     xor     eax, 200000h    ; flip ID bit in EFLAGS
  465.     push    eax             ; save new EFLAGS value on stack
  466.     popfd                   ; replace current EFLAGS value
  467.     pushfd                  ; get new EFLAGS
  468.     pop     eax             ; store new EFLAGS in EAX
  469.     popfd                   ; restore original EFLAGS
  470.     xor     eax, ecx        ; can抰 toggle ID bit,
  471.     je      is_old_486      ; processor=old
  472.     mov     eax,1
  473.     db      0fh,0a2h        ;CPUID
  474. exitcpudetect:
  475.     pop ebx
  476.     ret
  477. end_cpu_is_386:
  478.     mov     eax,0300h
  479.     jmp     exitcpudetect
  480. is_old_486:
  481.     mov     eax,0400h
  482.     jmp     exitcpudetect
  483. IFDEF NOUNDERLINE
  484. cpudetect32     endp
  485. ELSE
  486. _cpudetect32    endp
  487. ENDIF
  488. ENDIF
  489. MAX_MATCH       equ     258
  490. MIN_MATCH       equ     3
  491. MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
  492. MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
  493. ;;; stack frame offsets
  494. chainlenwmask   equ  esp + 0    ; high word: current chain len
  495.                     ; low word: s->wmask
  496. window      equ  esp + 4    ; local copy of s->window
  497. windowbestlen   equ  esp + 8    ; s->window + bestlen
  498. scanstart   equ  esp + 16   ; first two bytes of string
  499. scanend     equ  esp + 12   ; last two bytes of string
  500. scanalign   equ  esp + 20   ; dword-misalignment of string
  501. nicematch   equ  esp + 24   ; a good enough match size
  502. bestlen     equ  esp + 28   ; size of best match so far
  503. scan        equ  esp + 32   ; ptr to string wanting match
  504. LocalVarsSize   equ 36
  505. ;   saved ebx   byte esp + 36
  506. ;   saved edi   byte esp + 40
  507. ;   saved esi   byte esp + 44
  508. ;   saved ebp   byte esp + 48
  509. ;   return address  byte esp + 52
  510. deflatestate    equ  esp + 56   ; the function arguments
  511. curmatch    equ  esp + 60
  512. ;;; Offsets for fields in the deflate_state structure. These numbers
  513. ;;; are calculated from the definition of deflate_state, with the
  514. ;;; assumption that the compiler will dword-align the fields. (Thus,
  515. ;;; changing the definition of deflate_state could easily cause this
  516. ;;; program to crash horribly, without so much as a warning at
  517. ;;; compile time. Sigh.)
  518. dsWSize     equ 36+zlib1222add
  519. dsWMask     equ 44+zlib1222add
  520. dsWindow    equ 48+zlib1222add
  521. dsPrev      equ 56+zlib1222add
  522. dsMatchLen  equ 88+zlib1222add
  523. dsPrevMatch equ 92+zlib1222add
  524. dsStrStart  equ 100+zlib1222add
  525. dsMatchStart    equ 104+zlib1222add
  526. dsLookahead equ 108+zlib1222add
  527. dsPrevLen   equ 112+zlib1222add
  528. dsMaxChainLen   equ 116+zlib1222add
  529. dsGoodMatch equ 132+zlib1222add
  530. dsNiceMatch equ 136+zlib1222add
  531. ;;; match.asm -- Pentium-Pro-optimized version of longest_match()
  532. ;;; Written for zlib 1.1.2
  533. ;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
  534. ;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
  535. ;;;
  536. ;;; This is free software; you can redistribute it and/or modify it
  537. ;;; under the terms of the GNU General Public License.
  538. ;GLOBAL _longest_match, _match_init
  539. ;SECTION    .text
  540. ;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
  541. ;_longest_match:
  542. IFDEF NOOLDPENTIUMCODE
  543.     IFDEF NOUNDERLINE
  544.     longest_match       proc near
  545.     ELSE
  546.     _longest_match      proc near
  547.     ENDIF
  548. ELSE
  549.     IFDEF NOUNDERLINE
  550.     longest_match_686   proc near
  551.     ELSE
  552.     _longest_match_686  proc near
  553.     ENDIF
  554. ENDIF
  555. ;;; Save registers that the compiler may be using, and adjust esp to
  556. ;;; make room for our stack frame.
  557.         push    ebp
  558.         push    edi
  559.         push    esi
  560.         push    ebx
  561.         sub esp, LocalVarsSize
  562. ;;; Retrieve the function arguments. ecx will hold cur_match
  563. ;;; throughout the entire function. edx will hold the pointer to the
  564. ;;; deflate_state structure during the function's setup (before
  565. ;;; entering the main loop.
  566.         mov edx, [deflatestate]
  567.         mov ecx, [curmatch]
  568. ;;; uInt wmask = s->w_mask;
  569. ;;; unsigned chain_length = s->max_chain_length;
  570. ;;; if (s->prev_length >= s->good_match) {
  571. ;;;     chain_length >>= 2;
  572. ;;; }
  573.         mov eax, [edx + dsPrevLen]
  574.         mov ebx, [edx + dsGoodMatch]
  575.         cmp eax, ebx
  576.         mov eax, [edx + dsWMask]
  577.         mov ebx, [edx + dsMaxChainLen]
  578.         jl  LastMatchGood
  579.         shr ebx, 2
  580. LastMatchGood:
  581. ;;; chainlen is decremented once beforehand so that the function can
  582. ;;; use the sign flag instead of the zero flag for the exit test.
  583. ;;; It is then shifted into the high word, to make room for the wmask
  584. ;;; value, which it will always accompany.
  585.         dec ebx
  586.         shl ebx, 16
  587.         or  ebx, eax
  588.         mov [chainlenwmask], ebx
  589. ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
  590.         mov eax, [edx + dsNiceMatch]
  591.         mov ebx, [edx + dsLookahead]
  592.         cmp ebx, eax
  593.         jl  LookaheadLess
  594.         mov ebx, eax
  595. LookaheadLess:  mov [nicematch], ebx
  596. ;;; register Bytef *scan = s->window + s->strstart;
  597.         mov esi, [edx + dsWindow]
  598.         mov [window], esi
  599.         mov ebp, [edx + dsStrStart]
  600.         lea edi, [esi + ebp]
  601.         mov [scan], edi
  602. ;;; Determine how many bytes the scan ptr is off from being
  603. ;;; dword-aligned.
  604.         mov eax, edi
  605.         neg eax
  606.         and eax, 3
  607.         mov [scanalign], eax
  608. ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
  609. ;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
  610.         mov eax, [edx + dsWSize]
  611.         sub eax, MIN_LOOKAHEAD
  612.         sub ebp, eax
  613.         jg  LimitPositive
  614.         xor ebp, ebp
  615. LimitPositive:
  616. ;;; int best_len = s->prev_length;
  617.         mov eax, [edx + dsPrevLen]
  618.         mov [bestlen], eax
  619. ;;; Store the sum of s->window + best_len in esi locally, and in esi.
  620.         add esi, eax
  621.         mov [windowbestlen], esi
  622. ;;; register ush scan_start = *(ushf*)scan;
  623. ;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
  624. ;;; Posf *prev = s->prev;
  625.         movzx   ebx, word ptr [edi]
  626.         mov [scanstart], ebx
  627.         movzx   ebx, word ptr [edi + eax - 1]
  628.         mov [scanend], ebx
  629.         mov edi, [edx + dsPrev]
  630. ;;; Jump into the main loop.
  631.         mov edx, [chainlenwmask]
  632.         jmp short LoopEntry
  633. align 4
  634. ;;; do {
  635. ;;;     match = s->window + cur_match;
  636. ;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
  637. ;;;         *(ushf*)match != scan_start) continue;
  638. ;;;     [...]
  639. ;;; } while ((cur_match = prev[cur_match & wmask]) > limit
  640. ;;;          && --chain_length != 0);
  641. ;;;
  642. ;;; Here is the inner loop of the function. The function will spend the
  643. ;;; majority of its time in this loop, and majority of that time will
  644. ;;; be spent in the first ten instructions.
  645. ;;;
  646. ;;; Within this loop:
  647. ;;; ebx = scanend
  648. ;;; ecx = curmatch
  649. ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
  650. ;;; esi = windowbestlen - i.e., (window + bestlen)
  651. ;;; edi = prev
  652. ;;; ebp = limit
  653. LookupLoop:
  654.         and ecx, edx
  655.         movzx   ecx, word ptr [edi + ecx*2]
  656.         cmp ecx, ebp
  657.         jbe LeaveNow
  658.         sub edx, 00010000h
  659.         js  LeaveNow
  660. LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]
  661.         cmp eax, ebx
  662.         jnz LookupLoop
  663.         mov eax, [window]
  664.         movzx   eax, word ptr [eax + ecx]
  665.         cmp eax, [scanstart]
  666.         jnz LookupLoop
  667. ;;; Store the current value of chainlen.
  668.         mov [chainlenwmask], edx
  669. ;;; Point edi to the string under scrutiny, and esi to the string we
  670. ;;; are hoping to match it up with. In actuality, esi and edi are
  671. ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
  672. ;;; initialized to -(MAX_MATCH_8 - scanalign).
  673.         mov esi, [window]
  674.         mov edi, [scan]
  675.         add esi, ecx
  676.         mov eax, [scanalign]
  677.         mov edx, 0fffffef8h; -(MAX_MATCH_8)
  678.         lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
  679.         lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
  680. ;;; Test the strings for equality, 8 bytes at a time. At the end,
  681. ;;; adjust edx so that it is offset to the exact byte that mismatched.
  682. ;;;
  683. ;;; We already know at this point that the first three bytes of the
  684. ;;; strings match each other, and they can be safely passed over before
  685. ;;; starting the compare loop. So what this code does is skip over 0-3
  686. ;;; bytes, as much as necessary in order to dword-align the edi
  687. ;;; pointer. (esi will still be misaligned three times out of four.)
  688. ;;;
  689. ;;; It should be confessed that this loop usually does not represent
  690. ;;; much of the total running time. Replacing it with a more
  691. ;;; straightforward "rep cmpsb" would not drastically degrade
  692. ;;; performance.
  693. LoopCmps:
  694.         mov eax, [esi + edx]
  695.         xor eax, [edi + edx]
  696.         jnz LeaveLoopCmps
  697.         mov eax, [esi + edx + 4]
  698.         xor eax, [edi + edx + 4]
  699.         jnz LeaveLoopCmps4
  700.         add edx, 8
  701.         jnz LoopCmps
  702.         jmp short LenMaximum
  703. LeaveLoopCmps4: add edx, 4
  704. LeaveLoopCmps:  test    eax, 0000FFFFh
  705.         jnz LenLower
  706.         add edx,  2
  707.         shr eax, 16
  708. LenLower:   sub al, 1
  709.         adc edx, 0
  710. ;;; Calculate the length of the match. If it is longer than MAX_MATCH,
  711. ;;; then automatically accept it as the best possible match and leave.
  712.         lea eax, [edi + edx]
  713.         mov edi, [scan]
  714.         sub eax, edi
  715.         cmp eax, MAX_MATCH
  716.         jge LenMaximum
  717. ;;; If the length of the match is not longer than the best match we
  718. ;;; have so far, then forget it and return to the lookup loop.
  719.         mov edx, [deflatestate]
  720.         mov ebx, [bestlen]
  721.         cmp eax, ebx
  722.         jg  LongerMatch
  723.         mov esi, [windowbestlen]
  724.         mov edi, [edx + dsPrev]
  725.         mov ebx, [scanend]
  726.         mov edx, [chainlenwmask]
  727.         jmp LookupLoop
  728. ;;;         s->match_start = cur_match;
  729. ;;;         best_len = len;
  730. ;;;         if (len >= nice_match) break;
  731. ;;;         scan_end = *(ushf*)(scan+best_len-1);
  732. LongerMatch:    mov ebx, [nicematch]
  733.         mov [bestlen], eax
  734.         mov [edx + dsMatchStart], ecx
  735.         cmp eax, ebx
  736.         jge LeaveNow
  737.         mov esi, [window]
  738.         add esi, eax
  739.         mov [windowbestlen], esi
  740.         movzx   ebx, word ptr [edi + eax - 1]
  741.         mov edi, [edx + dsPrev]
  742.         mov [scanend], ebx
  743.         mov edx, [chainlenwmask]
  744.         jmp LookupLoop
  745. ;;; Accept the current string, with the maximum possible length.
  746. LenMaximum: mov edx, [deflatestate]
  747.         mov dword ptr [bestlen], MAX_MATCH
  748.         mov [edx + dsMatchStart], ecx
  749. ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
  750. ;;; return s->lookahead;
  751. LeaveNow:
  752.         mov edx, [deflatestate]
  753.         mov ebx, [bestlen]
  754.         mov eax, [edx + dsLookahead]
  755.         cmp ebx, eax
  756.         jg  LookaheadRet
  757.         mov eax, ebx
  758. LookaheadRet:
  759. ;;; Restore the stack and return from whence we came.
  760.         add esp, LocalVarsSize
  761.         pop ebx
  762.         pop esi
  763.         pop edi
  764.         pop ebp
  765.         ret
  766. ; please don't remove this string !
  767. ; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
  768.     db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
  769. IFDEF NOOLDPENTIUMCODE
  770.     IFDEF NOUNDERLINE
  771.     longest_match       endp
  772.     ELSE
  773.     _longest_match      endp
  774.     ENDIF
  775.     IFDEF NOUNDERLINE
  776.     match_init      proc near
  777.                     ret
  778.     match_init      endp
  779.     ELSE
  780.     _match_init     proc near
  781.                     ret
  782.     _match_init     endp
  783.     ENDIF    
  784. ELSE
  785.     IFDEF NOUNDERLINE
  786.     longest_match_686   endp
  787.     ELSE
  788.     _longest_match_686  endp
  789.     ENDIF
  790. ENDIF
  791. _TEXT   ends
  792. end