⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 match.asm

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 ASM
字号:
; match.asm -- Pentium-Pro optimized version of longest_match();; Updated for zlib 1.1.3 and converted to MASM 6.1x; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>;                    and Chuck Walbourn <chuckw@kinesoft.com>; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>;; This is free software; you can redistribute it and/or modify it; under the terms of the GNU General Public License.; Based on match.S; Written for zlib 1.1.2; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>	.686P	.MODEL	FLAT;===========================================================================; EQUATES;===========================================================================MAX_MATCH	EQU 258MIN_MATCH	EQU 3MIN_LOOKAHEAD	EQU (MAX_MATCH + MIN_MATCH + 1)MAX_MATCH_8	EQU ((MAX_MATCH + 7) AND (NOT 7));===========================================================================; STRUCTURES;===========================================================================; This STRUCT assumes a 4-byte alignmentDEFLATE_STATE	STRUCTds_strm			dd ?ds_status		dd ?ds_pending_buf		dd ?ds_pending_buf_size	dd ?ds_pending_out		dd ?ds_pending		dd ?ds_wrap			dd ?ds_data_type		db ?ds_method		db ?			db ?	; padding			db ?	; paddingds_last_flush		dd ?ds_w_size		dd ?	; usedds_w_bits		dd ?ds_w_mask		dd ?	; usedds_window		dd ?	; usedds_window_size		dd ?ds_prev			dd ?	; usedds_head			dd ?ds_ins_h		dd ?ds_hash_size		dd ?ds_hash_bits		dd ?ds_hash_mask		dd ?ds_hash_shift		dd ?ds_block_start		dd ?ds_match_length		dd ?	; usedds_prev_match		dd ?	; usedds_match_available	dd ?ds_strstart		dd ?	; usedds_match_start		dd ?	; usedds_lookahead		dd ?	; usedds_prev_length		dd ?	; usedds_max_chain_length	dd ?	; usedds_max_laxy_match	dd ?ds_level		dd ?ds_strategy		dd ?ds_good_match		dd ?	; usedds_nice_match		dd ?	; used; Don't need anymore of the struct for matchDEFLATE_STATE	ENDS;===========================================================================; CODE;===========================================================================_TEXT	SEGMENT;---------------------------------------------------------------------------; match_init;---------------------------------------------------------------------------	ALIGN	4PUBLIC	_match_init_match_init	PROC	; no initialization needed	ret_match_init	ENDP;---------------------------------------------------------------------------; uInt longest_match(deflate_state *deflatestate, IPos curmatch);---------------------------------------------------------------------------	ALIGN	4PUBLIC	_longest_match_longest_match	PROC; Since this code uses EBP for a scratch register, the stack frame must; be manually constructed and referenced relative to the ESP register.; Stack image; Variableschainlenwmask	=  0	; high word: current chain len			; low word: s->wmaskwindow		=  4	; local copy of s->windowwindowbestlen	=  8	; s->window + bestlenscanend		= 12	; last two bytes of stringscanstart	= 16	; first two bytes of stringscanalign	= 20	; dword-misalignment of stringnicematch	= 24	; a good enough match sizebestlen		= 28	; size of best match so farscan		= 32	; ptr to string wanting matchvarsize		= 36	; number of bytes (also offset to last saved register); Saved Registers (actually pushed into place)ebx_save	= 36edi_save	= 40esi_save	= 44ebp_save	= 48; Parametersretaddr		= 52deflatestate	= 56curmatch	= 60; Save registers that the compiler may be using	push	ebp	push	edi	push	esi	push	ebx; Allocate local variable space	sub	esp,varsize; 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, [esp+deflatestate]ASSUME	edx:PTR DEFLATE_STATE	mov	ecx, [esp+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].ds_prev_length	mov	ebx, [edx].ds_good_match	cmp	eax, ebx	mov	eax, [edx].ds_w_mask	mov	ebx, [edx].ds_max_chain_length	jl	SHORT LastMatchGood	shr	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	ebx	shl	ebx, 16	or	ebx, eax	mov	[esp+chainlenwmask], ebx; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;	mov	eax, [edx].ds_nice_match	mov	ebx, [edx].ds_lookahead	cmp	ebx, eax	jl	SHORT LookaheadLess	mov	ebx, eaxLookaheadLess:	mov	[esp+nicematch], ebx;/* register Bytef *scan = s->window + s->strstart;                     */	mov	esi, [edx].ds_window	mov	[esp+window], esi	mov	ebp, [edx].ds_strstart	lea	edi, [esi+ebp]	mov	[esp+scan],edi;/* Determine how many bytes the scan ptr is off from being             */;/* dword-aligned.                                                      */	mov	eax, edi	neg	eax	and	eax, 3	mov	[esp+scanalign], eax;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ?                      */;/*     s->strstart - (IPos)MAX_DIST(s) : NIL;                          */	mov	eax, [edx].ds_w_size	sub	eax, MIN_LOOKAHEAD	sub	ebp, eax	jg	SHORT LimitPositive	xor	ebp, ebpLimitPositive:;/* int best_len = s->prev_length;                                      */	mov	eax, [edx].ds_prev_length	mov	[esp+bestlen], eax;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */	add	esi, eax	mov	[esp+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	[esp+scanstart], ebx	movzx	ebx, WORD PTR[eax+edi-1]	mov	[esp+scanend], ebx	mov	edi, [edx].ds_prev;/* Jump into the main loop.                                            */	mov	edx, [esp+chainlenwmask]	jmp	SHORT LoopEntry;/* 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 = limit; */	ALIGN	4LookupLoop:	and	ecx, edx	movzx	ecx, WORD PTR[edi+ecx*2]	cmp	ecx, ebp	jbe	LeaveNow	sub	edx, 000010000H	js	LeaveNowLoopEntry:	movzx	eax, WORD PTR[esi+ecx-1]	cmp	eax, ebx	jnz	SHORT LookupLoop	mov	eax, [esp+window]	movzx	eax, WORD PTR[eax+ecx]	cmp	eax, [esp+scanstart]	jnz	SHORT LookupLoop;/* Store the current value of chainlen.                                */	mov	[esp+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, [esp+window]	mov	edi, [esp+scan]	add	esi, ecx	mov	eax, [esp+scanalign]	mov	edx, -MAX_MATCH_8	lea	edi, [edi+eax+MAX_MATCH_8]	lea	esi, [esi+eax+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, DWORD PTR[esi+edx]	xor	eax, DWORD PTR[edi+edx]	jnz	SHORT LeaveLoopCmps	mov	eax, DWORD PTR[esi+edx+4]	xor	eax, DWORD PTR[edi+edx+4]	jnz	SHORT LeaveLoopCmps4	add	edx, 8	jnz	SHORT LoopCmps	jmp	LenMaximum	ALIGN	4LeaveLoopCmps4:	add	edx, 4LeaveLoopCmps:	test	eax, 00000FFFFH	jnz	SHORT LenLower	add	edx, 2	shr	eax, 16LenLower:	sub	al, 1	adc	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, [esp+scan]	sub	eax, edi	cmp	eax, MAX_MATCH	jge	SHORT 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, [esp+deflatestate]	mov	ebx, [esp+bestlen]	cmp	eax, ebx	jg	SHORT LongerMatch	mov	esi, [esp+windowbestlen]	mov	edi, [edx].ds_prev	mov	ebx, [esp+scanend]	mov	edx, [esp+chainlenwmask]	jmp	LookupLoop	ALIGN	4;/*         s->match_start = cur_match;                                 */;/*         best_len = len;                                             */;/*         if (len >= nice_match) break;                               */;/*         scan_end = *(ushf*)(scan+best_len-1);                       */LongerMatch:	mov	ebx, [esp+nicematch]	mov	[esp+bestlen], eax	mov	[edx].ds_match_start, ecx	cmp	eax, ebx	jge	SHORT LeaveNow	mov	esi, [esp+window]	add	esi, eax	mov	[esp+windowbestlen], esi	movzx	ebx, WORD PTR[edi+eax-1]	mov	edi, [edx].ds_prev	mov	[esp+scanend], ebx	mov	edx, [esp+chainlenwmask]	jmp	LookupLoop	ALIGN	4;/* Accept the current string, with the maximum possible length.        */LenMaximum:	mov	edx, [esp+deflatestate]	mov	DWORD PTR[esp+bestlen], MAX_MATCH	mov	[edx].ds_match_start, ecx;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len;          */;/* return s->lookahead;                                                */LeaveNow:	mov	edx, [esp+deflatestate]	mov	ebx, [esp+bestlen]	mov	eax, [edx].ds_lookahead	cmp	ebx, eax	jg	SHORT LookaheadRet	mov	eax, ebxLookaheadRet:; Restore the stack and return from whence we came.	add	esp, varsize	pop	ebx	pop	esi	pop	edi	pop	ebp	ret_longest_match	ENDP_TEXT	ENDSEND

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -