Home | History | Annotate | Line # | Download | only in masmx86
match686.asm revision 1.1
      1  1.1  christos ; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86
      2  1.1  christos ; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
      3  1.1  christos ; File written by Gilles Vollant, by converting match686.S from Brian Raiter
      4  1.1  christos ; for MASM. This is as assembly version of longest_match
      5  1.1  christos ;  from Jean-loup Gailly in deflate.c
      6  1.1  christos ;
      7  1.1  christos ;         http://www.zlib.net
      8  1.1  christos ;         http://www.winimage.com/zLibDll
      9  1.1  christos ;         http://www.muppetlabs.com/~breadbox/software/assembly.html
     10  1.1  christos ;
     11  1.1  christos ; For Visual C++ 4.x and higher and ML 6.x and higher
     12  1.1  christos ;   ml.exe is distributed in
     13  1.1  christos ;  http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64
     14  1.1  christos ;
     15  1.1  christos ; this file contain two implementation of longest_match
     16  1.1  christos ;
     17  1.1  christos ;  this longest_match was written by Brian raiter (1998), optimized for Pentium Pro
     18  1.1  christos ;   (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom)
     19  1.1  christos ;
     20  1.1  christos ;  for using an assembly version of longest_match, you need define ASMV in project
     21  1.1  christos ;
     22  1.1  christos ;    compile the asm file running
     23  1.1  christos ;           ml /coff /Zi /c /Flmatch686.lst match686.asm
     24  1.1  christos ;    and do not include match686.obj in your project
     25  1.1  christos ;
     26  1.1  christos ; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for
     27  1.1  christos ;  Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor
     28  1.1  christos ;  with autoselect (with cpu detection code)
     29  1.1  christos ;  if you want support the old pentium optimization, you can still use these version
     30  1.1  christos ;
     31  1.1  christos ; this file is not optimized for old pentium, but it compatible with all x86 32 bits
     32  1.1  christos ; processor (starting 80386)
     33  1.1  christos ;
     34  1.1  christos ;
     35  1.1  christos ; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2
     36  1.1  christos 
     37  1.1  christos ;uInt longest_match(s, cur_match)
     38  1.1  christos ;    deflate_state *s;
     39  1.1  christos ;    IPos cur_match;                             /* current match */
     40  1.1  christos 
     41  1.1  christos     NbStack         equ     76
     42  1.1  christos     cur_match       equ     dword ptr[esp+NbStack-0]
     43  1.1  christos     str_s           equ     dword ptr[esp+NbStack-4]
     44  1.1  christos ; 5 dword on top (ret,ebp,esi,edi,ebx)
     45  1.1  christos     adrret          equ     dword ptr[esp+NbStack-8]
     46  1.1  christos     pushebp         equ     dword ptr[esp+NbStack-12]
     47  1.1  christos     pushedi         equ     dword ptr[esp+NbStack-16]
     48  1.1  christos     pushesi         equ     dword ptr[esp+NbStack-20]
     49  1.1  christos     pushebx         equ     dword ptr[esp+NbStack-24]
     50  1.1  christos 
     51  1.1  christos     chain_length    equ     dword ptr [esp+NbStack-28]
     52  1.1  christos     limit           equ     dword ptr [esp+NbStack-32]
     53  1.1  christos     best_len        equ     dword ptr [esp+NbStack-36]
     54  1.1  christos     window          equ     dword ptr [esp+NbStack-40]
     55  1.1  christos     prev            equ     dword ptr [esp+NbStack-44]
     56  1.1  christos     scan_start      equ      word ptr [esp+NbStack-48]
     57  1.1  christos     wmask           equ     dword ptr [esp+NbStack-52]
     58  1.1  christos     match_start_ptr equ     dword ptr [esp+NbStack-56]
     59  1.1  christos     nice_match      equ     dword ptr [esp+NbStack-60]
     60  1.1  christos     scan            equ     dword ptr [esp+NbStack-64]
     61  1.1  christos 
     62  1.1  christos     windowlen       equ     dword ptr [esp+NbStack-68]
     63  1.1  christos     match_start     equ     dword ptr [esp+NbStack-72]
     64  1.1  christos     strend          equ     dword ptr [esp+NbStack-76]
     65  1.1  christos     NbStackAdd      equ     (NbStack-24)
     66  1.1  christos 
     67  1.1  christos     .386p
     68  1.1  christos 
     69  1.1  christos     name    gvmatch
     70  1.1  christos     .MODEL  FLAT
     71  1.1  christos 
     72  1.1  christos 
     73  1.1  christos 
     74  1.1  christos ;  all the +zlib1222add offsets are due to the addition of fields
     75  1.1  christos ;  in zlib in the deflate_state structure since the asm code was first written
     76  1.1  christos ;  (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
     77  1.1  christos ;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
     78  1.1  christos ;  if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
     79  1.1  christos 
     80  1.1  christos     zlib1222add         equ     8
     81  1.1  christos 
     82  1.1  christos ;  Note : these value are good with a 8 bytes boundary pack structure
     83  1.1  christos     dep_chain_length    equ     74h+zlib1222add
     84  1.1  christos     dep_window          equ     30h+zlib1222add
     85  1.1  christos     dep_strstart        equ     64h+zlib1222add
     86  1.1  christos     dep_prev_length     equ     70h+zlib1222add
     87  1.1  christos     dep_nice_match      equ     88h+zlib1222add
     88  1.1  christos     dep_w_size          equ     24h+zlib1222add
     89  1.1  christos     dep_prev            equ     38h+zlib1222add
     90  1.1  christos     dep_w_mask          equ     2ch+zlib1222add
     91  1.1  christos     dep_good_match      equ     84h+zlib1222add
     92  1.1  christos     dep_match_start     equ     68h+zlib1222add
     93  1.1  christos     dep_lookahead       equ     6ch+zlib1222add
     94  1.1  christos 
     95  1.1  christos 
     96  1.1  christos _TEXT                   segment
     97  1.1  christos 
     98  1.1  christos IFDEF NOUNDERLINE
     99  1.1  christos             public  longest_match
    100  1.1  christos             public  match_init
    101  1.1  christos ELSE
    102  1.1  christos             public  _longest_match
    103  1.1  christos             public  _match_init
    104  1.1  christos ENDIF
    105  1.1  christos 
    106  1.1  christos     MAX_MATCH           equ     258
    107  1.1  christos     MIN_MATCH           equ     3
    108  1.1  christos     MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)
    109  1.1  christos 
    110  1.1  christos 
    111  1.1  christos 
    112  1.1  christos MAX_MATCH       equ     258
    113  1.1  christos MIN_MATCH       equ     3
    114  1.1  christos MIN_LOOKAHEAD   equ     (MAX_MATCH + MIN_MATCH + 1)
    115  1.1  christos MAX_MATCH_8_     equ     ((MAX_MATCH + 7) AND 0FFF0h)
    116  1.1  christos 
    117  1.1  christos 
    118  1.1  christos ;;; stack frame offsets
    119  1.1  christos 
    120  1.1  christos chainlenwmask   equ  esp + 0    ; high word: current chain len
    121  1.1  christos                     ; low word: s->wmask
    122  1.1  christos window      equ  esp + 4    ; local copy of s->window
    123  1.1  christos windowbestlen   equ  esp + 8    ; s->window + bestlen
    124  1.1  christos scanstart   equ  esp + 16   ; first two bytes of string
    125  1.1  christos scanend     equ  esp + 12   ; last two bytes of string
    126  1.1  christos scanalign   equ  esp + 20   ; dword-misalignment of string
    127  1.1  christos nicematch   equ  esp + 24   ; a good enough match size
    128  1.1  christos bestlen     equ  esp + 28   ; size of best match so far
    129  1.1  christos scan        equ  esp + 32   ; ptr to string wanting match
    130  1.1  christos 
    131  1.1  christos LocalVarsSize   equ 36
    132  1.1  christos ;   saved ebx   byte esp + 36
    133  1.1  christos ;   saved edi   byte esp + 40
    134  1.1  christos ;   saved esi   byte esp + 44
    135  1.1  christos ;   saved ebp   byte esp + 48
    136  1.1  christos ;   return address  byte esp + 52
    137  1.1  christos deflatestate    equ  esp + 56   ; the function arguments
    138  1.1  christos curmatch    equ  esp + 60
    139  1.1  christos 
    140  1.1  christos ;;; Offsets for fields in the deflate_state structure. These numbers
    141  1.1  christos ;;; are calculated from the definition of deflate_state, with the
    142  1.1  christos ;;; assumption that the compiler will dword-align the fields. (Thus,
    143  1.1  christos ;;; changing the definition of deflate_state could easily cause this
    144  1.1  christos ;;; program to crash horribly, without so much as a warning at
    145  1.1  christos ;;; compile time. Sigh.)
    146  1.1  christos 
    147  1.1  christos dsWSize     equ 36+zlib1222add
    148  1.1  christos dsWMask     equ 44+zlib1222add
    149  1.1  christos dsWindow    equ 48+zlib1222add
    150  1.1  christos dsPrev      equ 56+zlib1222add
    151  1.1  christos dsMatchLen  equ 88+zlib1222add
    152  1.1  christos dsPrevMatch equ 92+zlib1222add
    153  1.1  christos dsStrStart  equ 100+zlib1222add
    154  1.1  christos dsMatchStart    equ 104+zlib1222add
    155  1.1  christos dsLookahead equ 108+zlib1222add
    156  1.1  christos dsPrevLen   equ 112+zlib1222add
    157  1.1  christos dsMaxChainLen   equ 116+zlib1222add
    158  1.1  christos dsGoodMatch equ 132+zlib1222add
    159  1.1  christos dsNiceMatch equ 136+zlib1222add
    160  1.1  christos 
    161  1.1  christos 
    162  1.1  christos ;;; match686.asm -- Pentium-Pro-optimized version of longest_match()
    163  1.1  christos ;;; Written for zlib 1.1.2
    164  1.1  christos ;;; Copyright (C) 1998 Brian Raiter <breadbox (a] muppetlabs.com>
    165  1.1  christos ;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html
    166  1.1  christos ;;;
    167  1.1  christos ;;
    168  1.1  christos ;;  This software is provided 'as-is', without any express or implied
    169  1.1  christos ;;  warranty.  In no event will the authors be held liable for any damages
    170  1.1  christos ;;  arising from the use of this software.
    171  1.1  christos ;;
    172  1.1  christos ;;  Permission is granted to anyone to use this software for any purpose,
    173  1.1  christos ;;  including commercial applications, and to alter it and redistribute it
    174  1.1  christos ;;  freely, subject to the following restrictions:
    175  1.1  christos ;;
    176  1.1  christos ;;  1. The origin of this software must not be misrepresented; you must not
    177  1.1  christos ;;     claim that you wrote the original software. If you use this software
    178  1.1  christos ;;     in a product, an acknowledgment in the product documentation would be
    179  1.1  christos ;;     appreciated but is not required.
    180  1.1  christos ;;  2. Altered source versions must be plainly marked as such, and must not be
    181  1.1  christos ;;     misrepresented as being the original software
    182  1.1  christos ;;  3. This notice may not be removed or altered from any source distribution.
    183  1.1  christos ;;
    184  1.1  christos 
    185  1.1  christos ;GLOBAL _longest_match, _match_init
    186  1.1  christos 
    187  1.1  christos 
    188  1.1  christos ;SECTION    .text
    189  1.1  christos 
    190  1.1  christos ;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
    191  1.1  christos 
    192  1.1  christos ;_longest_match:
    193  1.1  christos     IFDEF NOUNDERLINE
    194  1.1  christos     longest_match       proc near
    195  1.1  christos     ELSE
    196  1.1  christos     _longest_match      proc near
    197  1.1  christos     ENDIF
    198  1.1  christos .FPO (9, 4, 0, 0, 1, 0)
    199  1.1  christos 
    200  1.1  christos ;;; Save registers that the compiler may be using, and adjust esp to
    201  1.1  christos ;;; make room for our stack frame.
    202  1.1  christos 
    203  1.1  christos         push    ebp
    204  1.1  christos         push    edi
    205  1.1  christos         push    esi
    206  1.1  christos         push    ebx
    207  1.1  christos         sub esp, LocalVarsSize
    208  1.1  christos 
    209  1.1  christos ;;; Retrieve the function arguments. ecx will hold cur_match
    210  1.1  christos ;;; throughout the entire function. edx will hold the pointer to the
    211  1.1  christos ;;; deflate_state structure during the function's setup (before
    212  1.1  christos ;;; entering the main loop.
    213  1.1  christos 
    214  1.1  christos         mov edx, [deflatestate]
    215  1.1  christos         mov ecx, [curmatch]
    216  1.1  christos 
    217  1.1  christos ;;; uInt wmask = s->w_mask;
    218  1.1  christos ;;; unsigned chain_length = s->max_chain_length;
    219  1.1  christos ;;; if (s->prev_length >= s->good_match) {
    220  1.1  christos ;;;     chain_length >>= 2;
    221  1.1  christos ;;; }
    222  1.1  christos 
    223  1.1  christos         mov eax, [edx + dsPrevLen]
    224  1.1  christos         mov ebx, [edx + dsGoodMatch]
    225  1.1  christos         cmp eax, ebx
    226  1.1  christos         mov eax, [edx + dsWMask]
    227  1.1  christos         mov ebx, [edx + dsMaxChainLen]
    228  1.1  christos         jl  LastMatchGood
    229  1.1  christos         shr ebx, 2
    230  1.1  christos LastMatchGood:
    231  1.1  christos 
    232  1.1  christos ;;; chainlen is decremented once beforehand so that the function can
    233  1.1  christos ;;; use the sign flag instead of the zero flag for the exit test.
    234  1.1  christos ;;; It is then shifted into the high word, to make room for the wmask
    235  1.1  christos ;;; value, which it will always accompany.
    236  1.1  christos 
    237  1.1  christos         dec ebx
    238  1.1  christos         shl ebx, 16
    239  1.1  christos         or  ebx, eax
    240  1.1  christos         mov [chainlenwmask], ebx
    241  1.1  christos 
    242  1.1  christos ;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
    243  1.1  christos 
    244  1.1  christos         mov eax, [edx + dsNiceMatch]
    245  1.1  christos         mov ebx, [edx + dsLookahead]
    246  1.1  christos         cmp ebx, eax
    247  1.1  christos         jl  LookaheadLess
    248  1.1  christos         mov ebx, eax
    249  1.1  christos LookaheadLess:  mov [nicematch], ebx
    250  1.1  christos 
    251  1.1  christos ;;; register Bytef *scan = s->window + s->strstart;
    252  1.1  christos 
    253  1.1  christos         mov esi, [edx + dsWindow]
    254  1.1  christos         mov [window], esi
    255  1.1  christos         mov ebp, [edx + dsStrStart]
    256  1.1  christos         lea edi, [esi + ebp]
    257  1.1  christos         mov [scan], edi
    258  1.1  christos 
    259  1.1  christos ;;; Determine how many bytes the scan ptr is off from being
    260  1.1  christos ;;; dword-aligned.
    261  1.1  christos 
    262  1.1  christos         mov eax, edi
    263  1.1  christos         neg eax
    264  1.1  christos         and eax, 3
    265  1.1  christos         mov [scanalign], eax
    266  1.1  christos 
    267  1.1  christos ;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
    268  1.1  christos ;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;
    269  1.1  christos 
    270  1.1  christos         mov eax, [edx + dsWSize]
    271  1.1  christos         sub eax, MIN_LOOKAHEAD
    272  1.1  christos         sub ebp, eax
    273  1.1  christos         jg  LimitPositive
    274  1.1  christos         xor ebp, ebp
    275  1.1  christos LimitPositive:
    276  1.1  christos 
    277  1.1  christos ;;; int best_len = s->prev_length;
    278  1.1  christos 
    279  1.1  christos         mov eax, [edx + dsPrevLen]
    280  1.1  christos         mov [bestlen], eax
    281  1.1  christos 
    282  1.1  christos ;;; Store the sum of s->window + best_len in esi locally, and in esi.
    283  1.1  christos 
    284  1.1  christos         add esi, eax
    285  1.1  christos         mov [windowbestlen], esi
    286  1.1  christos 
    287  1.1  christos ;;; register ush scan_start = *(ushf*)scan;
    288  1.1  christos ;;; register ush scan_end   = *(ushf*)(scan+best_len-1);
    289  1.1  christos ;;; Posf *prev = s->prev;
    290  1.1  christos 
    291  1.1  christos         movzx   ebx, word ptr [edi]
    292  1.1  christos         mov [scanstart], ebx
    293  1.1  christos         movzx   ebx, word ptr [edi + eax - 1]
    294  1.1  christos         mov [scanend], ebx
    295  1.1  christos         mov edi, [edx + dsPrev]
    296  1.1  christos 
    297  1.1  christos ;;; Jump into the main loop.
    298  1.1  christos 
    299  1.1  christos         mov edx, [chainlenwmask]
    300  1.1  christos         jmp short LoopEntry
    301  1.1  christos 
    302  1.1  christos align 4
    303  1.1  christos 
    304  1.1  christos ;;; do {
    305  1.1  christos ;;;     match = s->window + cur_match;
    306  1.1  christos ;;;     if (*(ushf*)(match+best_len-1) != scan_end ||
    307  1.1  christos ;;;         *(ushf*)match != scan_start) continue;
    308  1.1  christos ;;;     [...]
    309  1.1  christos ;;; } while ((cur_match = prev[cur_match & wmask]) > limit
    310  1.1  christos ;;;          && --chain_length != 0);
    311  1.1  christos ;;;
    312  1.1  christos ;;; Here is the inner loop of the function. The function will spend the
    313  1.1  christos ;;; majority of its time in this loop, and majority of that time will
    314  1.1  christos ;;; be spent in the first ten instructions.
    315  1.1  christos ;;;
    316  1.1  christos ;;; Within this loop:
    317  1.1  christos ;;; ebx = scanend
    318  1.1  christos ;;; ecx = curmatch
    319  1.1  christos ;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
    320  1.1  christos ;;; esi = windowbestlen - i.e., (window + bestlen)
    321  1.1  christos ;;; edi = prev
    322  1.1  christos ;;; ebp = limit
    323  1.1  christos 
    324  1.1  christos LookupLoop:
    325  1.1  christos         and ecx, edx
    326  1.1  christos         movzx   ecx, word ptr [edi + ecx*2]
    327  1.1  christos         cmp ecx, ebp
    328  1.1  christos         jbe LeaveNow
    329  1.1  christos         sub edx, 00010000h
    330  1.1  christos         js  LeaveNow
    331  1.1  christos LoopEntry:  movzx   eax, word ptr [esi + ecx - 1]
    332  1.1  christos         cmp eax, ebx
    333  1.1  christos         jnz LookupLoop
    334  1.1  christos         mov eax, [window]
    335  1.1  christos         movzx   eax, word ptr [eax + ecx]
    336  1.1  christos         cmp eax, [scanstart]
    337  1.1  christos         jnz LookupLoop
    338  1.1  christos 
    339  1.1  christos ;;; Store the current value of chainlen.
    340  1.1  christos 
    341  1.1  christos         mov [chainlenwmask], edx
    342  1.1  christos 
    343  1.1  christos ;;; Point edi to the string under scrutiny, and esi to the string we
    344  1.1  christos ;;; are hoping to match it up with. In actuality, esi and edi are
    345  1.1  christos ;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
    346  1.1  christos ;;; initialized to -(MAX_MATCH_8 - scanalign).
    347  1.1  christos 
    348  1.1  christos         mov esi, [window]
    349  1.1  christos         mov edi, [scan]
    350  1.1  christos         add esi, ecx
    351  1.1  christos         mov eax, [scanalign]
    352  1.1  christos         mov edx, 0fffffef8h; -(MAX_MATCH_8)
    353  1.1  christos         lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]
    354  1.1  christos         lea esi, [esi + eax + 0108h] ;MAX_MATCH_8]
    355  1.1  christos 
    356  1.1  christos ;;; Test the strings for equality, 8 bytes at a time. At the end,
    357  1.1  christos ;;; adjust edx so that it is offset to the exact byte that mismatched.
    358  1.1  christos ;;;
    359  1.1  christos ;;; We already know at this point that the first three bytes of the
    360  1.1  christos ;;; strings match each other, and they can be safely passed over before
    361  1.1  christos ;;; starting the compare loop. So what this code does is skip over 0-3
    362  1.1  christos ;;; bytes, as much as necessary in order to dword-align the edi
    363  1.1  christos ;;; pointer. (esi will still be misaligned three times out of four.)
    364  1.1  christos ;;;
    365  1.1  christos ;;; It should be confessed that this loop usually does not represent
    366  1.1  christos ;;; much of the total running time. Replacing it with a more
    367  1.1  christos ;;; straightforward "rep cmpsb" would not drastically degrade
    368  1.1  christos ;;; performance.
    369  1.1  christos 
    370  1.1  christos LoopCmps:
    371  1.1  christos         mov eax, [esi + edx]
    372  1.1  christos         xor eax, [edi + edx]
    373  1.1  christos         jnz LeaveLoopCmps
    374  1.1  christos         mov eax, [esi + edx + 4]
    375  1.1  christos         xor eax, [edi + edx + 4]
    376  1.1  christos         jnz LeaveLoopCmps4
    377  1.1  christos         add edx, 8
    378  1.1  christos         jnz LoopCmps
    379  1.1  christos         jmp short LenMaximum
    380  1.1  christos LeaveLoopCmps4: add edx, 4
    381  1.1  christos LeaveLoopCmps:  test    eax, 0000FFFFh
    382  1.1  christos         jnz LenLower
    383  1.1  christos         add edx,  2
    384  1.1  christos         shr eax, 16
    385  1.1  christos LenLower:   sub al, 1
    386  1.1  christos         adc edx, 0
    387  1.1  christos 
    388  1.1  christos ;;; Calculate the length of the match. If it is longer than MAX_MATCH,
    389  1.1  christos ;;; then automatically accept it as the best possible match and leave.
    390  1.1  christos 
    391  1.1  christos         lea eax, [edi + edx]
    392  1.1  christos         mov edi, [scan]
    393  1.1  christos         sub eax, edi
    394  1.1  christos         cmp eax, MAX_MATCH
    395  1.1  christos         jge LenMaximum
    396  1.1  christos 
    397  1.1  christos ;;; If the length of the match is not longer than the best match we
    398  1.1  christos ;;; have so far, then forget it and return to the lookup loop.
    399  1.1  christos 
    400  1.1  christos         mov edx, [deflatestate]
    401  1.1  christos         mov ebx, [bestlen]
    402  1.1  christos         cmp eax, ebx
    403  1.1  christos         jg  LongerMatch
    404  1.1  christos         mov esi, [windowbestlen]
    405  1.1  christos         mov edi, [edx + dsPrev]
    406  1.1  christos         mov ebx, [scanend]
    407  1.1  christos         mov edx, [chainlenwmask]
    408  1.1  christos         jmp LookupLoop
    409  1.1  christos 
    410  1.1  christos ;;;         s->match_start = cur_match;
    411  1.1  christos ;;;         best_len = len;
    412  1.1  christos ;;;         if (len >= nice_match) break;
    413  1.1  christos ;;;         scan_end = *(ushf*)(scan+best_len-1);
    414  1.1  christos 
    415  1.1  christos LongerMatch:    mov ebx, [nicematch]
    416  1.1  christos         mov [bestlen], eax
    417  1.1  christos         mov [edx + dsMatchStart], ecx
    418  1.1  christos         cmp eax, ebx
    419  1.1  christos         jge LeaveNow
    420  1.1  christos         mov esi, [window]
    421  1.1  christos         add esi, eax
    422  1.1  christos         mov [windowbestlen], esi
    423  1.1  christos         movzx   ebx, word ptr [edi + eax - 1]
    424  1.1  christos         mov edi, [edx + dsPrev]
    425  1.1  christos         mov [scanend], ebx
    426  1.1  christos         mov edx, [chainlenwmask]
    427  1.1  christos         jmp LookupLoop
    428  1.1  christos 
    429  1.1  christos ;;; Accept the current string, with the maximum possible length.
    430  1.1  christos 
    431  1.1  christos LenMaximum: mov edx, [deflatestate]
    432  1.1  christos         mov dword ptr [bestlen], MAX_MATCH
    433  1.1  christos         mov [edx + dsMatchStart], ecx
    434  1.1  christos 
    435  1.1  christos ;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
    436  1.1  christos ;;; return s->lookahead;
    437  1.1  christos 
    438  1.1  christos LeaveNow:
    439  1.1  christos         mov edx, [deflatestate]
    440  1.1  christos         mov ebx, [bestlen]
    441  1.1  christos         mov eax, [edx + dsLookahead]
    442  1.1  christos         cmp ebx, eax
    443  1.1  christos         jg  LookaheadRet
    444  1.1  christos         mov eax, ebx
    445  1.1  christos LookaheadRet:
    446  1.1  christos 
    447  1.1  christos ;;; Restore the stack and return from whence we came.
    448  1.1  christos 
    449  1.1  christos         add esp, LocalVarsSize
    450  1.1  christos         pop ebx
    451  1.1  christos         pop esi
    452  1.1  christos         pop edi
    453  1.1  christos         pop ebp
    454  1.1  christos 
    455  1.1  christos         ret
    456  1.1  christos ; please don't remove this string !
    457  1.1  christos ; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary!
    458  1.1  christos     db     0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah
    459  1.1  christos 
    460  1.1  christos 
    461  1.1  christos     IFDEF NOUNDERLINE
    462  1.1  christos     longest_match       endp
    463  1.1  christos     ELSE
    464  1.1  christos     _longest_match      endp
    465  1.1  christos     ENDIF
    466  1.1  christos 
    467  1.1  christos     IFDEF NOUNDERLINE
    468  1.1  christos     match_init      proc near
    469  1.1  christos                     ret
    470  1.1  christos     match_init      endp
    471  1.1  christos     ELSE
    472  1.1  christos     _match_init     proc near
    473  1.1  christos                     ret
    474  1.1  christos     _match_init     endp
    475  1.1  christos     ENDIF
    476  1.1  christos 
    477  1.1  christos 
    478  1.1  christos _TEXT   ends
    479  1.1  christos end
    480