URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [zlib/] [contrib/] [masmx86/] [gvmat32.asm] - Rev 745
Compare with Previous | Blame | View Log
; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.; File written by Gilles Vollant, by modifiying the longest_match; from Jean-loup Gailly in deflate.c;; http://www.zlib.net; http://www.winimage.com/zLibDll; http://www.muppetlabs.com/~breadbox/software/assembly.html;; For Visual C++ 4.x and higher and ML 6.x and higher; ml.exe is in directory \MASM611C of Win95 DDK; ml.exe is also distributed in http://www.masm32.com/masmdl.htm; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/;; this file contain two implementation of longest_match;; longest_match_7fff : written 1996 by Gilles Vollant optimized for; first Pentium. Assume s->w_mask == 0x7fff; longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro;; for using an seembly version of longest_match, you need define ASMV in project; There is two way in using gvmat32.asm;; A) Suggested method; if you want include both longest_match_7fff and longest_match_686; compile the asm file running; ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm; and include gvmat32c.c in your project; if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff,; longest_match_7fff will be used; if you have a more modern CPU (Pentium Pro, II and higher); longest_match_686 will be used; on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used,; but this is not a sitation you'll find often;; B) Alternative; if you are not interresed in old cpu performance and want the smaller; binaries possible;; compile the asm file running; ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm; and do not include gvmat32c.c in your project (ou define also; NOOLDPENTIUMCODE);; note : as I known, longest_match_686 is very faster than longest_match_7fff; on pentium Pro/II/III, faster (but less) in P4, but it seem; longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8;; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2;uInt longest_match_7fff(s, cur_match); deflate_state *s;; IPos cur_match; /* current match */NbStack equ 76cur_match equ dword ptr[esp+NbStack-0]str_s equ dword ptr[esp+NbStack-4]; 5 dword on top (ret,ebp,esi,edi,ebx)adrret equ dword ptr[esp+NbStack-8]pushebp equ dword ptr[esp+NbStack-12]pushedi equ dword ptr[esp+NbStack-16]pushesi equ dword ptr[esp+NbStack-20]pushebx equ dword ptr[esp+NbStack-24]chain_length equ dword ptr [esp+NbStack-28]limit equ dword ptr [esp+NbStack-32]best_len equ dword ptr [esp+NbStack-36]window equ dword ptr [esp+NbStack-40]prev equ dword ptr [esp+NbStack-44]scan_start equ word ptr [esp+NbStack-48]wmask equ dword ptr [esp+NbStack-52]match_start_ptr equ dword ptr [esp+NbStack-56]nice_match equ dword ptr [esp+NbStack-60]scan equ dword ptr [esp+NbStack-64]windowlen equ dword ptr [esp+NbStack-68]match_start equ dword ptr [esp+NbStack-72]strend equ dword ptr [esp+NbStack-76]NbStackAdd equ (NbStack-24).386pname gvmatch.MODEL FLAT; all the +zlib1222add offsets are due to the addition of fields; in zlib in the deflate_state structure since the asm code was first written; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").zlib1222add equ 8; Note : these value are good with a 8 bytes boundary pack structuredep_chain_length equ 74h+zlib1222adddep_window equ 30h+zlib1222adddep_strstart equ 64h+zlib1222adddep_prev_length equ 70h+zlib1222adddep_nice_match equ 88h+zlib1222adddep_w_size equ 24h+zlib1222adddep_prev equ 38h+zlib1222adddep_w_mask equ 2ch+zlib1222adddep_good_match equ 84h+zlib1222adddep_match_start equ 68h+zlib1222adddep_lookahead equ 6ch+zlib1222add_TEXT segmentIFDEF NOUNDERLINEIFDEF NOOLDPENTIUMCODEpublic longest_matchpublic match_initELSEpublic longest_match_7fffpublic cpudetect32public longest_match_686ENDIFELSEIFDEF NOOLDPENTIUMCODEpublic _longest_matchpublic _match_initELSEpublic _longest_match_7fffpublic _cpudetect32public _longest_match_686ENDIFENDIFMAX_MATCH equ 258MIN_MATCH equ 3MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)IFNDEF NOOLDPENTIUMCODEIFDEF NOUNDERLINElongest_match_7fff proc nearELSE_longest_match_7fff proc nearENDIFmov edx,[esp+4]push ebppush edipush esipush ebxsub esp,NbStackAdd; initialize or check the variables used in match.asm.mov ebp,edx; chain_length = s->max_chain_length; if (prev_length>=good_match) chain_length >>= 2mov edx,[ebp+dep_chain_length]mov ebx,[ebp+dep_prev_length]cmp [ebp+dep_good_match],ebxja noshrshr edx,2noshr:; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loopinc edxmov edi,[ebp+dep_nice_match]mov chain_length,edxmov eax,[ebp+dep_lookahead]cmp eax,edi; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;jae nolookaheadnicematchmov edi,eaxnolookaheadnicematch:; best_len = s->prev_lengthmov best_len,ebx; window = s->windowmov esi,[ebp+dep_window]mov ecx,[ebp+dep_strstart]mov window,esimov nice_match,edi; scan = window + strstartadd esi,ecxmov scan,esi; dx = *windowmov dx,word ptr [esi]; bx = *(window+best_len-1)mov bx,word ptr [esi+ebx-1]add esi,MAX_MATCH-1; scan_start = *scanmov scan_start,dx; strend = scan + MAX_MATCH-1mov strend,esi; bx = scan_end = *(window+best_len-1); IPos limit = s->strstart > (IPos)MAX_DIST(s) ?; s->strstart - (IPos)MAX_DIST(s) : NIL;mov esi,[ebp+dep_w_size]sub esi,MIN_LOOKAHEAD; here esi = MAX_DIST(s)sub ecx,esija nodistxor ecx,ecxnodist:mov limit,ecx; prev = s->prevmov edx,[ebp+dep_prev]mov prev,edx;mov edx,dword ptr [ebp+dep_match_start]mov bp,scan_startmov eax,cur_matchmov match_start,edxmov edx,windowmov edi,edxadd edi,best_lenmov esi,prevdec edi; windowlen = window + best_len -1mov windowlen,edijmp beginloop2align 4; here, in the loop; eax = ax = cur_match; ecx = limit; bx = scan_end; bp = scan_start; edi = windowlen (window + best_len -1); esi = prev;// here; chain_length <=16normalbeg0add16:add chain_length,16jz exitloopnormalbeg0:cmp word ptr[edi+eax],bxje normalbeg2norollrcontlabnoroll:; cur_match = prev[cur_match & wmask]and eax,7fffhmov ax,word ptr[esi+eax*2]; if cur_match > limit, go to exitloopcmp ecx,eaxjnb exitloop; if --chain_length != 0, go to exitloopdec chain_lengthjnz normalbeg0jmp exitloopnormalbeg2noroll:; if (scan_start==*(cur_match+window)) goto normalbeg2cmp bp,word ptr[edx+eax]jne rcontlabnorolljmp normalbeg2contloop3:mov edi,windowlen; cur_match = prev[cur_match & wmask]and eax,7fffhmov ax,word ptr[esi+eax*2]; if cur_match > limit, go to exitloopcmp ecx,eaxjnbexitloopshort1:jnb exitloop; if --chain_length != 0, go to exitloop; begin the main loopbeginloop2:sub chain_length,16+1; if chain_length <=16, don't use the unrolled loopjna normalbeg0add16do16:cmp word ptr[edi+eax],bxje normalbeg2dc0maccn MACRO laband eax,7fffhmov ax,word ptr[esi+eax*2]cmp ecx,eaxjnb exitloopcmp word ptr[edi+eax],bxje labENDMrcontloop0:maccn normalbeg2dc1rcontloop1:maccn normalbeg2dc2rcontloop2:maccn normalbeg2dc3rcontloop3:maccn normalbeg2dc4rcontloop4:maccn normalbeg2dc5rcontloop5:maccn normalbeg2dc6rcontloop6:maccn normalbeg2dc7rcontloop7:maccn normalbeg2dc8rcontloop8:maccn normalbeg2dc9rcontloop9:maccn normalbeg2dc10rcontloop10:maccn short normalbeg2dc11rcontloop11:maccn short normalbeg2dc12rcontloop12:maccn short normalbeg2dc13rcontloop13:maccn short normalbeg2dc14rcontloop14:maccn short normalbeg2dc15rcontloop15:and eax,7fffhmov ax,word ptr[esi+eax*2]cmp ecx,eaxjnb exitloopsub chain_length,16ja do16jmp normalbeg0add16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;normbeg MACRO rcontlab,valsub; if we are here, we know that *(match+best_len-1) == scan_endcmp bp,word ptr[edx+eax]; if (match != scan_start) goto rcontlabjne rcontlab; calculate the good chain_length, and we'll compare scan and match stringadd chain_length,16-valsubjmp iseqENDMnormalbeg2dc11:normbeg rcontloop11,11normalbeg2dc12:normbeg short rcontloop12,12normalbeg2dc13:normbeg short rcontloop13,13normalbeg2dc14:normbeg short rcontloop14,14normalbeg2dc15:normbeg short rcontloop15,15normalbeg2dc10:normbeg rcontloop10,10normalbeg2dc9:normbeg rcontloop9,9normalbeg2dc8:normbeg rcontloop8,8normalbeg2dc7:normbeg rcontloop7,7normalbeg2dc6:normbeg rcontloop6,6normalbeg2dc5:normbeg rcontloop5,5normalbeg2dc4:normbeg rcontloop4,4normalbeg2dc3:normbeg rcontloop3,3normalbeg2dc2:normbeg rcontloop2,2normalbeg2dc1:normbeg rcontloop1,1normalbeg2dc0:normbeg rcontloop0,0; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_endnormalbeg2:mov edi,windowcmp bp,word ptr[edi+eax]jne contloop3 ; if *(ushf*)match != scan_start, continueiseq:; if we are here, we know that *(match+best_len-1) == scan_end; and (match == scan_start)mov edi,edxmov esi,scan ; esi = scanadd edi,eax ; edi = window + cur_match = matchmov edx,[esi+3] ; compare manually dword at match+3xor edx,[edi+3] ; and scan +3jz begincompare ; if equal, go to long compare; we will determine the unmatch byte and calculate len (in esi)or dl,dlje eq1rrmov esi,3jmp trfinvaleq1rr:or dx,dxje eq1mov esi,4jmp trfinvaleq1:and edx,0ffffffhjz eq11mov esi,5jmp trfinvaleq11:mov esi,6jmp trfinvalbegincompare:; here we now scan and match begin sameadd edi,6add esi,6mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytesrepe cmpsd ; loop until mismatchje trfin ; go to trfin if not unmatch; we determine the unmatch bytesub esi,4mov edx,[edi-4]xor edx,[esi]or dl,dljnz trfininc esior dx,dxjnz trfininc esiand edx,0ffffffhjnz trfininc esitrfin:sub esi,scan ; esi = lentrfinval:; here we have finised compare, and esi contain len of equal stringcmp esi,best_len ; if len > best_len, go newbestlenja short newbestlen; now we restore edx, ecx and esi, for the big loopmov esi,prevmov ecx,limitmov edx,windowjmp contloop3newbestlen:mov best_len,esi ; len become best_lenmov match_start,eax ; save new position as match_startcmp esi,nice_match ; if best_len >= nice_match, exitjae exitloopmov ecx,scanmov edx,window ; restore edx=windowadd ecx,esiadd esi,edxdec esimov windowlen,esi ; windowlen = window + best_len-1mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end; now we restore ecx and esi, for the big loop :mov esi,prevmov ecx,limitjmp contloop3exitloop:; exit : s->match_start=match_startmov ebx,match_startmov ebp,str_smov ecx,best_lenmov dword ptr [ebp+dep_match_start],ebxmov eax,dword ptr [ebp+dep_lookahead]cmp ecx,eaxja minexlomov eax,ecxminexlo:; return min(best_len,s->lookahead); restore stack and register ebx,esi,edi,ebpadd esp,NbStackAddpop ebxpop esipop edipop ebpretInfoAuthor:; please don't remove this string !; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ahIFDEF NOUNDERLINElongest_match_7fff endpELSE_longest_match_7fff endpENDIFIFDEF NOUNDERLINEcpudetect32 proc nearELSE_cpudetect32 proc nearENDIFpush ebxpushfd ; push original EFLAGSpop eax ; get original EFLAGSmov ecx, eax ; save original EFLAGSxor eax, 40000h ; flip AC bit in EFLAGSpush eax ; save new EFLAGS value on stackpopfd ; replace current EFLAGS valuepushfd ; get new EFLAGSpop eax ; store new EFLAGS in EAXjz end_cpu_is_386 ; jump if 80386 processorpush ecxpopfd ; restore AC bit in EFLAGS firstpushfdpushfdpop ecxmov eax, ecx ; get original EFLAGSxor eax, 200000h ; flip ID bit in EFLAGSpush eax ; save new EFLAGS value on stackpopfd ; replace current EFLAGS valuepushfd ; get new EFLAGSpop eax ; store new EFLAGS in EAXpopfd ; restore original EFLAGSje is_old_486 ; processor=oldmov eax,1db 0fh,0a2h ;CPUIDexitcpudetect:pop ebxretend_cpu_is_386:mov eax,0300hjmp exitcpudetectis_old_486:mov eax,0400hjmp exitcpudetectIFDEF NOUNDERLINEcpudetect32 endpELSE_cpudetect32 endpENDIFENDIFMAX_MATCH equ 258MIN_MATCH equ 3MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1)MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h);;; stack frame offsetschainlenwmask equ esp + 0 ; high word: current chain len; low word: s->wmaskwindow equ esp + 4 ; local copy of s->windowwindowbestlen equ esp + 8 ; s->window + bestlenscanstart equ esp + 16 ; first two bytes of stringscanend equ esp + 12 ; last two bytes of stringscanalign equ esp + 20 ; dword-misalignment of stringnicematch equ esp + 24 ; a good enough match sizebestlen equ esp + 28 ; size of best match so farscan equ esp + 32 ; ptr to string wanting matchLocalVarsSize equ 36; saved ebx byte esp + 36; saved edi byte esp + 40; saved esi byte esp + 44; saved ebp byte esp + 48; return address byte esp + 52deflatestate equ esp + 56 ; the function argumentscurmatch equ esp + 60;;; Offsets for fields in the deflate_state structure. These numbers;;; are calculated from the definition of deflate_state, with the;;; assumption that the compiler will dword-align the fields. (Thus,;;; changing the definition of deflate_state could easily cause this;;; program to crash horribly, without so much as a warning at;;; compile time. Sigh.)dsWSize equ 36+zlib1222adddsWMask equ 44+zlib1222adddsWindow equ 48+zlib1222adddsPrev equ 56+zlib1222adddsMatchLen equ 88+zlib1222adddsPrevMatch equ 92+zlib1222adddsStrStart equ 100+zlib1222adddsMatchStart equ 104+zlib1222adddsLookahead equ 108+zlib1222adddsPrevLen equ 112+zlib1222adddsMaxChainLen equ 116+zlib1222adddsGoodMatch equ 132+zlib1222adddsNiceMatch equ 136+zlib1222add;;; match.asm -- Pentium-Pro-optimized version of longest_match();;; Written for zlib 1.1.2;;; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html;;;;;; This is free software; you can redistribute it and/or modify it;;; under the terms of the GNU General Public License.;GLOBAL _longest_match, _match_init;SECTION .text;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch);_longest_match:IFDEF NOOLDPENTIUMCODEIFDEF NOUNDERLINElongest_match proc nearELSE_longest_match proc nearENDIFELSEIFDEF NOUNDERLINElongest_match_686 proc nearELSE_longest_match_686 proc nearENDIFENDIF;;; Save registers that the compiler may be using, and adjust esp to;;; make room for our stack frame.push ebppush edipush esipush ebxsub esp, LocalVarsSize;;; Retrieve the function arguments. ecx will hold cur_match;;; throughout the entire function. edx will hold the pointer to the;;; deflate_state structure during the function's setup (before;;; entering the main loop.mov edx, [deflatestate]mov ecx, [curmatch];;; uInt wmask = s->w_mask;;;; unsigned chain_length = s->max_chain_length;;;; if (s->prev_length >= s->good_match) {;;; chain_length >>= 2;;;; }mov eax, [edx + dsPrevLen]mov ebx, [edx + dsGoodMatch]cmp eax, ebxmov eax, [edx + dsWMask]mov ebx, [edx + dsMaxChainLen]jl LastMatchGoodshr ebx, 2LastMatchGood:;;; chainlen is decremented once beforehand so that the function can;;; use the sign flag instead of the zero flag for the exit test.;;; It is then shifted into the high word, to make room for the wmask;;; value, which it will always accompany.dec ebxshl ebx, 16or ebx, eaxmov [chainlenwmask], ebx;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;mov eax, [edx + dsNiceMatch]mov ebx, [edx + dsLookahead]cmp ebx, eaxjl LookaheadLessmov ebx, eaxLookaheadLess: mov [nicematch], ebx;;; register Bytef *scan = s->window + s->strstart;mov esi, [edx + dsWindow]mov [window], esimov ebp, [edx + dsStrStart]lea edi, [esi + ebp]mov [scan], edi;;; Determine how many bytes the scan ptr is off from being;;; dword-aligned.mov eax, edineg eaxand eax, 3mov [scanalign], eax;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?;;; s->strstart - (IPos)MAX_DIST(s) : NIL;mov eax, [edx + dsWSize]sub eax, MIN_LOOKAHEADsub ebp, eaxjg LimitPositivexor ebp, ebpLimitPositive:;;; int best_len = s->prev_length;mov eax, [edx + dsPrevLen]mov [bestlen], eax;;; Store the sum of s->window + best_len in esi locally, and in esi.add esi, eaxmov [windowbestlen], esi;;; register ush scan_start = *(ushf*)scan;;;; register ush scan_end = *(ushf*)(scan+best_len-1);;;; Posf *prev = s->prev;movzx ebx, word ptr [edi]mov [scanstart], ebxmovzx ebx, word ptr [edi + eax - 1]mov [scanend], ebxmov edi, [edx + dsPrev];;; Jump into the main loop.mov edx, [chainlenwmask]jmp short LoopEntryalign 4;;; do {;;; match = s->window + cur_match;;;; if (*(ushf*)(match+best_len-1) != scan_end ||;;; *(ushf*)match != scan_start) continue;;;; [...];;; } while ((cur_match = prev[cur_match & wmask]) > limit;;; && --chain_length != 0);;;;;;; Here is the inner loop of the function. The function will spend the;;; majority of its time in this loop, and majority of that time will;;; be spent in the first ten instructions.;;;;;; Within this loop:;;; ebx = scanend;;; ecx = curmatch;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask);;; esi = windowbestlen - i.e., (window + bestlen);;; edi = prev;;; ebp = limitLookupLoop:and ecx, edxmovzx ecx, word ptr [edi + ecx*2]cmp ecx, ebpjbe LeaveNowsub edx, 00010000hjs LeaveNowLoopEntry: movzx eax, word ptr [esi + ecx - 1]cmp eax, ebxjnz LookupLoopmov eax, [window]movzx eax, word ptr [eax + ecx]cmp eax, [scanstart]jnz LookupLoop;;; Store the current value of chainlen.mov [chainlenwmask], edx;;; Point edi to the string under scrutiny, and esi to the string we;;; are hoping to match it up with. In actuality, esi and edi are;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is;;; initialized to -(MAX_MATCH_8 - scanalign).mov esi, [window]mov edi, [scan]add esi, ecxmov eax, [scanalign]mov edx, 0fffffef8h; -(MAX_MATCH_8)lea edi, [edi + eax + 0108h] ;MAX_MATCH_8]lea esi, [esi + eax + 0108h] ;MAX_MATCH_8];;; Test the strings for equality, 8 bytes at a time. At the end,;;; adjust edx so that it is offset to the exact byte that mismatched.;;;;;; We already know at this point that the first three bytes of the;;; strings match each other, and they can be safely passed over before;;; starting the compare loop. So what this code does is skip over 0-3;;; bytes, as much as necessary in order to dword-align the edi;;; pointer. (esi will still be misaligned three times out of four.);;;;;; It should be confessed that this loop usually does not represent;;; much of the total running time. Replacing it with a more;;; straightforward "rep cmpsb" would not drastically degrade;;; performance.LoopCmps:mov eax, [esi + edx]xor eax, [edi + edx]jnz LeaveLoopCmpsmov eax, [esi + edx + 4]xor eax, [edi + edx + 4]jnz LeaveLoopCmps4add edx, 8jnz LoopCmpsjmp short LenMaximumLeaveLoopCmps4: add edx, 4LeaveLoopCmps: test eax, 0000FFFFhjnz LenLoweradd edx, 2shr eax, 16LenLower: sub al, 1adc edx, 0;;; Calculate the length of the match. If it is longer than MAX_MATCH,;;; then automatically accept it as the best possible match and leave.lea eax, [edi + edx]mov edi, [scan]sub eax, edicmp eax, MAX_MATCHjge LenMaximum;;; If the length of the match is not longer than the best match we;;; have so far, then forget it and return to the lookup loop.mov edx, [deflatestate]mov ebx, [bestlen]cmp eax, ebxjg LongerMatchmov esi, [windowbestlen]mov edi, [edx + dsPrev]mov ebx, [scanend]mov edx, [chainlenwmask]jmp LookupLoop;;; s->match_start = cur_match;;;; best_len = len;;;; if (len >= nice_match) break;;;; scan_end = *(ushf*)(scan+best_len-1);LongerMatch: mov ebx, [nicematch]mov [bestlen], eaxmov [edx + dsMatchStart], ecxcmp eax, ebxjge LeaveNowmov esi, [window]add esi, eaxmov [windowbestlen], esimovzx ebx, word ptr [edi + eax - 1]mov edi, [edx + dsPrev]mov [scanend], ebxmov edx, [chainlenwmask]jmp LookupLoop;;; Accept the current string, with the maximum possible length.LenMaximum: mov edx, [deflatestate]mov dword ptr [bestlen], MAX_MATCHmov [edx + dsMatchStart], ecx;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;;;; return s->lookahead;LeaveNow:mov edx, [deflatestate]mov ebx, [bestlen]mov eax, [edx + dsLookahead]cmp ebx, eaxjg LookaheadRetmov eax, ebxLookaheadRet:;;; Restore the stack and return from whence we came.add esp, LocalVarsSizepop ebxpop esipop edipop ebpret; please don't remove this string !; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ahIFDEF NOOLDPENTIUMCODEIFDEF NOUNDERLINElongest_match endpELSE_longest_match endpENDIFIFDEF NOUNDERLINEmatch_init proc nearretmatch_init endpELSE_match_init proc nearret_match_init endpENDIFELSEIFDEF NOUNDERLINElongest_match_686 endpELSE_longest_match_686 endpENDIFENDIF_TEXT endsend
