📄 gvmat32.asm
字号:
newbestlen:
mov best_len,esi ; len become best_len
mov match_start,eax ; save new position as match_start
cmp esi,nice_match ; if best_len >= nice_match, exit
jae exitloop
mov ecx,scan
mov edx,window ; restore edx=window
add ecx,esi
add esi,edx
dec esi
mov windowlen,esi ; windowlen = window + best_len-1
mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
; now we restore ecx and esi, for the big loop :
mov esi,prev
mov ecx,limit
jmp contloop3
exitloop:
; exit : s->match_start=match_start
mov ebx,match_start
mov ebp,str_s
mov ecx,best_len
mov dword ptr [ebp+dep_match_start],ebx
mov eax,dword ptr [ebp+dep_lookahead]
cmp ecx,eax
ja minexlo
mov eax,ecx
minexlo:
; return min(best_len,s->lookahead)
; restore stack and register ebx,esi,edi,ebp
add esp,NbStackAdd
pop ebx
pop esi
pop edi
pop ebp
ret
; now : the generic version
; (mask is not fixed)
longest_match_generic:
push ebp
push edi
push esi
push ebx
sub esp,NbStackAdd
; initialize or check the variables used in match.asm.
and eax,0ffffh
mov ebp,edx
mov wmask,eax
; chain_length = s->max_chain_length
; if (prev_length>=good_match) chain_length >>= 2
mov edx,[ebp+dep_chain_length]
mov ebx,[ebp+dep_prev_length]
cmp [ebp+dep_good_match],ebx
ja gnoshr
shr edx,2
gnoshr:
; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
inc edx
mov edi,[ebp+dep_nice_match]
mov chain_length,edx
mov eax,[ebp+dep_lookahead]
cmp eax,edi
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
jae gnolookaheadnicematch
mov edi,eax
gnolookaheadnicematch:
; best_len = s->prev_length
mov best_len,ebx
; window = s->window
mov esi,[ebp+dep_window]
mov ecx,[ebp+dep_strstart]
mov window,esi
mov nice_match,edi
; scan = window + strstart
add esi,ecx
mov scan,esi
; dx = *window
mov dx,word ptr [esi]
; bx = *(window+best_len-1)
mov bx,word ptr [esi+ebx-1]
add esi,MAX_MATCH-1
; scan_start = *scan
mov scan_start,dx
; strend = scan + MAX_MATCH-1
mov 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,esi
ja gnodist
xor ecx,ecx
gnodist:
mov limit,ecx
; prev = s->prev
mov edx,[ebp+dep_prev]
mov prev,edx
;
mov edx,dword ptr [ebp+dep_match_start]
mov bp,scan_start
mov eax,cur_match
mov match_start,edx
mov edx,window
mov edi,edx
add edi,best_len
mov esi,prev
dec edi
; windowlen = window + best_len -1
mov windowlen,edi
jmp gbeginloop2
align 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 <=16
gnormalbeg0add16:
add chain_length,16
jz gexitloop
gnormalbeg0:
cmp word ptr[edi+eax],bx
je gnormalbeg2noroll
grcontlabnoroll:
; cur_match = prev[cur_match & wmask]
and eax,wmask
mov ax,word ptr[esi+eax*2]
; if cur_match > limit, go to exitloop
cmp ecx,eax
jnb gexitloop
; if --chain_length != 0, go to exitloop
dec chain_length
jnz gnormalbeg0
jmp gexitloop
gnormalbeg2noroll:
; if (scan_start==*(cur_match+window)) goto normalbeg2
cmp bp,word ptr[edx+eax]
jne grcontlabnoroll
jmp gnormalbeg2
gcontloop3:
mov edi,windowlen
; cur_match = prev[cur_match & wmask]
and eax,wmask
mov ax,word ptr[esi+eax*2]
; if cur_match > limit, go to exitloop
cmp ecx,eax
gjnbexitloopshort1:
jnb gexitloop
; if --chain_length != 0, go to exitloop
; begin the main loop
gbeginloop2:
sub chain_length,16+1
; if chain_length <=16, don't use the unrolled loop
jna gnormalbeg0add16
gdo16:
cmp word ptr[edi+eax],bx
je gnormalbeg2dc0
gmaccn MACRO glab
and eax,wmask
mov ax,word ptr[esi+eax*2]
cmp ecx,eax
jnb gexitloop
cmp word ptr[edi+eax],bx
je glab
ENDM
grcontloop0:
gmaccn gnormalbeg2dc1
grcontloop1:
gmaccn gnormalbeg2dc2
grcontloop2:
gmaccn gnormalbeg2dc3
grcontloop3:
gmaccn gnormalbeg2dc4
grcontloop4:
gmaccn gnormalbeg2dc5
grcontloop5:
gmaccn gnormalbeg2dc6
grcontloop6:
gmaccn gnormalbeg2dc7
grcontloop7:
gmaccn gnormalbeg2dc8
grcontloop8:
gmaccn gnormalbeg2dc9
grcontloop9:
gmaccn gnormalbeg2dc10
grcontloop10:
gmaccn short gnormalbeg2dc11
grcontloop11:
gmaccn short gnormalbeg2dc12
grcontloop12:
gmaccn short gnormalbeg2dc13
grcontloop13:
gmaccn short gnormalbeg2dc14
grcontloop14:
gmaccn short gnormalbeg2dc15
grcontloop15:
and eax,wmask
mov ax,word ptr[esi+eax*2]
cmp ecx,eax
jnb gexitloop
sub chain_length,16
ja gdo16
jmp gnormalbeg0add16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gnormbeg MACRO grcontlab,valsub
; if we are here, we know that *(match+best_len-1) == scan_end
cmp bp,word ptr[edx+eax]
; if (match != scan_start) goto rcontlab
jne grcontlab
; calculate the good chain_length, and we'll compare scan and match string
add chain_length,16-valsub
jmp giseq
ENDM
gnormalbeg2dc11:
gnormbeg grcontloop11,11
gnormalbeg2dc12:
gnormbeg short grcontloop12,12
gnormalbeg2dc13:
gnormbeg short grcontloop13,13
gnormalbeg2dc14:
gnormbeg short grcontloop14,14
gnormalbeg2dc15:
gnormbeg short grcontloop15,15
gnormalbeg2dc10:
gnormbeg grcontloop10,10
gnormalbeg2dc9:
gnormbeg grcontloop9,9
gnormalbeg2dc8:
gnormbeg grcontloop8,8
gnormalbeg2dc7:
gnormbeg grcontloop7,7
gnormalbeg2dc6:
gnormbeg grcontloop6,6
gnormalbeg2dc5:
gnormbeg grcontloop5,5
gnormalbeg2dc4:
gnormbeg grcontloop4,4
gnormalbeg2dc3:
gnormbeg grcontloop3,3
gnormalbeg2dc2:
gnormbeg grcontloop2,2
gnormalbeg2dc1:
gnormbeg grcontloop1,1
gnormalbeg2dc0:
gnormbeg grcontloop0,0
; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
gnormalbeg2:
mov edi,window
cmp bp,word ptr[edi+eax]
jne gcontloop3 ; if *(ushf*)match != scan_start, continue
giseq:
; if we are here, we know that *(match+best_len-1) == scan_end
; and (match == scan_start)
mov edi,edx
mov esi,scan ; esi = scan
add edi,eax ; edi = window + cur_match = match
mov edx,[esi+3] ; compare manually dword at match+3
xor edx,[edi+3] ; and scan +3
jz gbegincompare ; if equal, go to long compare
; we will determine the unmatch byte and calculate len (in esi)
or dl,dl
je geq1rr
mov esi,3
jmp gtrfinval
geq1rr:
or dx,dx
je geq1
mov esi,4
jmp gtrfinval
geq1:
and edx,0ffffffh
jz geq11
mov esi,5
jmp gtrfinval
geq11:
mov esi,6
jmp gtrfinval
gbegincompare:
; here we now scan and match begin same
add edi,6
add esi,6
mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
repe cmpsd ; loop until mismatch
je gtrfin ; go to trfin if not unmatch
; we determine the unmatch byte
sub esi,4
mov edx,[edi-4]
xor edx,[esi]
or dl,dl
jnz gtrfin
inc esi
or dx,dx
jnz gtrfin
inc esi
and edx,0ffffffh
jnz gtrfin
inc esi
gtrfin:
sub esi,scan ; esi = len
gtrfinval:
; here we have finised compare, and esi contain len of equal string
cmp esi,best_len ; if len > best_len, go newbestlen
ja short gnewbestlen
; now we restore edx, ecx and esi, for the big loop
mov esi,prev
mov ecx,limit
mov edx,window
jmp gcontloop3
gnewbestlen:
mov best_len,esi ; len become best_len
mov match_start,eax ; save new position as match_start
cmp esi,nice_match ; if best_len >= nice_match, exit
jae gexitloop
mov ecx,scan
mov edx,window ; restore edx=window
add ecx,esi
add esi,edx
dec esi
mov windowlen,esi ; windowlen = window + best_len-1
mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
; now we restore ecx and esi, for the big loop :
mov esi,prev
mov ecx,limit
jmp gcontloop3
gexitloop:
; exit : s->match_start=match_start
mov ebx,match_start
mov ebp,str_s
mov ecx,best_len
mov dword ptr [ebp+dep_match_start],ebx
mov eax,dword ptr [ebp+dep_lookahead]
cmp ecx,eax
ja gminexlo
mov eax,ecx
gminexlo:
; return min(best_len,s->lookahead)
; restore stack and register ebx,esi,edi,ebp
add esp,NbStackAdd
pop ebx
pop esi
pop edi
pop ebp
ret
IFDEF NOUNDERLINE
longest_match endp
ELSE
_longest_match endp
ENDIF
_TEXT ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -