|
|
1.1 ! root 1: ; ! 2: ; Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, and Jean-loup Gailly. ! 3: ; Permission is granted to any individual or institution to use, copy, or ! 4: ; redistribute this software so long as all of the original files are included ! 5: ; unmodified, that it is not sold for profit, and that this copyright notice ! 6: ; is retained. ! 7: ; ! 8: ; match.asm by Jean-loup Gailly. ! 9: ! 10: ; match.asm, optimized version of longest_match() in deflate.c ! 11: ; Must be assembled with masm -ml. To be used only with C large model. ! 12: ; (For compact model, follow the instructions given below.) ! 13: ; This file is only optional. If you don't have masm or tasm, use the ! 14: ; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj ! 15: ; from OBJI). If you have reduced WSIZE in zip.h, then change its value ! 16: ; below. ! 17: ; ! 18: ; Turbo C 2.0 does not support static allocation of more than 64K bytes per ! 19: ; file, and does not have SS == DS. So TC and BC++ users must use: ! 20: ; tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match; ! 21: ; ! 22: ; To simplify the code, the option -DDYN_ALLOC is supported for OS/2 ! 23: ; only if the arrays are guaranteed to have zero offset (allocated by ! 24: ; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C. ! 25: ! 26: name match ! 27: ! 28: ; define LCODE as follows: ! 29: ; model: compact large (small and medium not supported here) ! 30: ; LCODE 0 1 ! 31: ! 32: LCODE equ 1 ! 33: DYN_ALLOC equ 1 ! 34: SS_NEQ_DS equ 1 ! 35: ; For Turbo C, define SS_NEQ_DS as 1, but for MSC you can leave it undefined. ! 36: ; The code is a little better when SS_NEQ_DS is not defined. ! 37: ! 38: ifndef DYN_ALLOC ! 39: extrn _prev : word ! 40: extrn _window : byte ! 41: prev equ _prev ; offset part ! 42: window equ _window ! 43: endif ! 44: ! 45: _DATA segment word public 'DATA' ! 46: extrn _match_start : word ! 47: extrn _prev_length : word ! 48: extrn _good_match : word ! 49: extrn _strstart : word ! 50: extrn _max_chain_length : word ! 51: ifdef DYN_ALLOC ! 52: extrn _prev : word ! 53: extrn _window : word ! 54: prev equ 0 ; offset forced to zero ! 55: window equ 0 ! 56: window_seg equ _window[2] ! 57: window_off equ 0 ! 58: else ! 59: wseg dw seg _window ! 60: window_seg equ wseg ! 61: window_off equ offset _window ! 62: endif ! 63: _DATA ends ! 64: ! 65: DGROUP group _DATA ! 66: ! 67: if LCODE ! 68: extrn _exit : far ! 69: else ! 70: extrn _exit : near ! 71: endif ! 72: ! 73: _TEXT segment word public 'CODE' ! 74: assume cs: _TEXT, ds: DGROUP ! 75: ! 76: public _match_init ! 77: public _longest_match ! 78: ! 79: MIN_MATCH equ 3 ! 80: MAX_MATCH equ 258 ! 81: WSIZE equ 8192 ; keep in sync with zip.h ! ! 82: WMASK equ (WSIZE-1) ! 83: MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) ! 84: MAX_DIST equ (WSIZE-MIN_LOOKAHEAD) ! 85: ! 86: prev_ptr dw seg _prev ; pointer to the prev array ! 87: ifdef SS_NEQ_DS ! 88: match_start dw 0 ; copy of _match_start if SS != DS ! 89: endif ! 90: ! 91: ; initialize or check the variables used in match.asm. ! 92: ! 93: if LCODE ! 94: _match_init proc far ! 95: else ! 96: _match_init proc near ! 97: endif ! 98: ifdef SS_NEQ_DS ! 99: ma_start equ cs:match_start ; does not work on OS/2 ! 100: else ! 101: assume ss: DGROUP ! 102: ma_start equ ss:_match_start ! 103: mov ax,ds ! 104: mov bx,ss ! 105: cmp ax,bx ; SS == DS? ! 106: jne error ! 107: endif ! 108: ifdef DYN_ALLOC ! 109: mov ax,_window[0] ; force zero offset ! 110: add ax,15 ! 111: mov cx,4 ! 112: shr ax,cl ! 113: add _window[2],ax ! 114: mov _window[0],0 ! 115: ! 116: mov ax,_prev[0] ; force zero offset ! 117: add ax,15 ! 118: mov cx,4 ! 119: shr ax,cl ! 120: add _prev[2],ax ! 121: mov _prev[0],0 ! 122: ifdef SS_NEQ_DS ! 123: mov ax,_prev[2] ; segment value ! 124: mov cs:prev_ptr,ax ; ugly write to code, crash on OS/2 ! 125: prev_seg equ cs:prev_ptr ! 126: else ! 127: prev_seg equ ss:_prev[2] ; works on OS/2 if SS == DS ! 128: endif ! 129: else ! 130: prev_seg equ cs:prev_ptr ! 131: endif ! 132: ret ! 133: error: call _exit ! 134: ! 135: _match_init endp ! 136: ! 137: ; ----------------------------------------------------------------------- ! 138: ; Set match_start to the longest match starting at the given string and ! 139: ; return its length. Matches shorter or equal to prev_length are discarded, ! 140: ; in which case the result is equal to prev_length and match_start is ! 141: ; garbage. ! 142: ; IN assertions: cur_match is the head of the hash chain for the current ! 143: ; string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 ! 144: ! 145: ; int longest_match(cur_match) ! 146: ! 147: if LCODE ! 148: _longest_match proc far ! 149: else ! 150: _longest_match proc near ! 151: endif ! 152: push bp ! 153: mov bp,sp ! 154: push di ! 155: push si ! 156: push ds ! 157: ! 158: if LCODE ! 159: cur_match equ word ptr [bp+6] ! 160: else ! 161: cur_match equ word ptr [bp+4] ! 162: endif ! 163: ; window equ es:window (es:0 for DYN_ALLOC) ! 164: ; prev equ ds:prev ! 165: ; match equ es:si ! 166: ; scan equ es:di ! 167: ; chain_length equ bp ! 168: ; best_len equ bx ! 169: ; limit equ dx ! 170: ! 171: mov si,cur_match ; use bp before it is destroyed ! 172: mov bp,_max_chain_length ; chain_length = max_chain_length ! 173: mov di,_strstart ! 174: mov dx,di ! 175: sub dx,MAX_DIST ; limit = strstart-MAX_DIST ! 176: jae limit_ok ! 177: sub dx,dx ; limit = NIL ! 178: limit_ok: ! 179: add di,2+window_off ; di = offset(window + strstart + 2) ! 180: mov bx,_prev_length ; best_len = prev_length ! 181: mov es,window_seg ! 182: mov ax,es:[bx+di-3] ; ax = scan[best_len-1..best_len] ! 183: mov cx,es:[di-2] ; cx = scan[0..1] ! 184: cmp bx,_good_match ; do we have a good match already? ! 185: mov ds,prev_seg ; (does not destroy the flags) ! 186: assume ds: nothing ! 187: jb do_scan ; good match? ! 188: shr bp,1 ; chain_length >>= 2 ! 189: shr bp,1 ! 190: jmp short do_scan ! 191: ! 192: even ; align destination of branch ! 193: long_loop: ! 194: ; at this point, ds:di == scan+2, ds:si == cur_match ! 195: mov ax,[bx+di-3] ; ax = scan[best_len-1..best_len] ! 196: mov cx,[di-2] ; cx = scan[0..1] ! 197: mov ds,prev_seg ; reset ds to address the prev array ! 198: short_loop: ! 199: dec bp ; --chain_length ! 200: jz the_end ! 201: ; at this point, di == scan+2, si = cur_match, ! 202: ; ax = scan[best_len-1..best_len] and cx = scan[0..1] ! 203: if (WSIZE-32768) ! 204: and si,WMASK ! 205: endif ! 206: shl si,1 ; cur_match as word index ! 207: mov si,prev[si] ; cur_match = prev[cur_match] ! 208: cmp si,dx ; cur_match <= limit ? ! 209: jbe the_end ! 210: do_scan: ! 211: cmp ax,word ptr es:window[bx+si-1] ; check match at best_len-1 ! 212: jne short_loop ! 213: cmp cx,word ptr es:window[si] ; check min_match_length match ! 214: jne short_loop ! 215: ! 216: lea si,window[si+2] ; si = match ! 217: mov ax,di ; ax = scan+2 ! 218: mov cx,es ! 219: mov ds,cx ; ds = es = window ! 220: mov cx,(MAX_MATCH-2)/2 ; scan for at most MAX_MATCH bytes ! 221: repe cmpsw ; loop until mismatch ! 222: je maxmatch ; match of length MAX_MATCH? ! 223: mismatch: ! 224: mov cl,[di-2] ; mismatch on first or second byte? ! 225: sub cl,[si-2] ; cl = 0 if first bytes equal ! 226: xchg ax,di ; di = scan+2, ax = end of scan ! 227: sub ax,di ; ax = len ! 228: sub si,ax ; si = cur_match + 2 + offset(window) ! 229: sub si,2+window_off ; si = cur_match ! 230: sub cl,1 ; set carry if cl == 0 (can't use DEC) ! 231: adc ax,0 ; ax = carry ? len+1 : len ! 232: cmp ax,bx ; len > best_len ? ! 233: jle long_loop ! 234: mov ma_start,si ; match_start = cur_match ! 235: mov bx,ax ; bx = best_len = len ! 236: cmp ax,MAX_MATCH ; len >= MAX_MATCH ? ! 237: jl long_loop ! 238: the_end: ! 239: pop ds ! 240: assume ds: DGROUP ! 241: ifdef SS_NEQ_DS ! 242: mov ax,ma_start ; garbage if no match found ! 243: mov ds:_match_start,ax ! 244: endif ! 245: pop si ! 246: pop di ! 247: pop bp ! 248: mov ax,bx ; result = ax = best_len ! 249: ret ! 250: maxmatch: ; come here if maximum match ! 251: cmpsb ; increment si and di ! 252: jmp mismatch ; force match_length = MAX_LENGTH ! 253: ! 254: _longest_match endp ! 255: ! 256: _TEXT ends ! 257: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.