annotate src/zlib-1.2.7/contrib/masmx86/match686.asm @ 83:ae30d91d2ffe

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