|
|
page ,132 title memcmp - compare to blocks of memory ;*** ;memcmp.asm - compare two blocks of memory ; ; Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved. ; ;Purpose: ; defines memcmp() - compare two memory blocks lexically and ; find their order. ; ;Revision History: ; 05-16-83 RN initial version ; 07-20-87 SKS rewritten for speed ; 05-17-88 SJM Add model-independent (large model) ifdef ; 08-04-88 SJM convert to cruntime/ add 32-bit support ; 08-23-88 JCR 386 cleanup ; 10-25-88 JCR General cleanup for 386-only code ; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright. ; 05-10-91 GJF Back to _cdecl, sigh... ; 05-01-95 GJF New, faster version from Intel! ; 05-09-95 GJF Replaced a bad ret with a good jz retnull (my editing ; error, not Intel's). ; 11-06-95 GJF Corrected order in which esi and edi are saved. ; 06-12-01 PML inc->add 1, dec->sub 1 for Pentium 4 perf (vs7#267015) ; ;*******************************************************************************
.xlist include cruntime.inc .list
page ;*** ;int memcmp(buf1, buf2, count) - compare memory for lexical order ; ;Purpose: ; Compares count bytes of memory starting at buf1 and buf2 ; and find if equal or which one is first in lexical order. ; ; Algorithm: ; int ; memcmp (buf1, buf2, count) ; char *buf1, *buf2; ; unsigned count; ; { ; if (!count) ; return(0); ; while (--count && *buf1 == *buf2) ; { ; buf1++; ; buf2++; ; } ; return(*buf1 - *buf2); ; } ; ;Entry: ; char *buf1, *buf2 - pointers to memory sections to compare ; unsigned count - length of sections to compare ; ;Exit: ; returns -1 if buf1 < buf2 ; returns 0 if buf1 == buf2 ; returns +1 if buf1 > buf2 ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************
CODESEG
public memcmp memcmp proc
.FPO ( 0, 3, 0, 0, 0, 0 )
mov eax,[esp+0ch] ; eax = counter test eax,eax ; test if counter is zero jz short retnull ; return 0
mov edx,[esp+4] ; edx = buf1 push esi push edi mov esi,edx ; esi = buf1 mov edi,[esp+10h] ; edi = buf2
; Check for dword (32 bit) alignment or edx,edi and edx,3 ; edx=0 iff buf1 are buf2 are aligned jz short dwords ; Strings are not aligned. If the caller knows the strings (buf1 and buf2) are ; different, the function may be called with length like -1. The difference ; may be found in the last dword of aligned string, and because the other ; string is misaligned it may cause page fault. So, to be safe. the comparison ; must be done byte by byte. test eax,1 jz short main_loop mov cl,[esi] cmp cl,[edi] jne short not_equal add esi,1 add edi,1 sub eax,1 jz short done ; eax is already 0
main_loop: mov cl,[esi] mov dl,[edi] cmp cl,dl jne short not_equal mov cl,[esi+1] mov dl,[edi+1] cmp cl,dl jne short not_equal add edi,2 add esi,2 sub eax,2 jnz short main_loop done: pop edi pop esi retnull: ret ; _cdecl return dwords: mov ecx,eax and eax,3 ; eax= counter for tail loop shr ecx,2 jz short tail_loop_start ; counter was >=4 so may check one dword rep cmpsd jz short tail_loop_start ; in last dword was difference mov ecx,[esi-4] ; load last dword from buf1 to ecx mov edx,[edi-4] ; load last dword from buf2 to edx cmp cl,dl ; test first bytes jne short difference_in_tail cmp ch,dh ; test seconds bytes jne short difference_in_tail shr ecx,10h shr edx,10h cmp cl,dl ; test third bytes jne short difference_in_tail cmp ch,dh ; they are different, but each one is bigger? ; jmp short difference_in_tail difference_in_tail: mov eax,0 ; buf1 < buf2 buf1 > buf2 not_equal: sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0 pop edi ; counter sbb eax,-1 ; AX=-1 AX=1 pop esi ret ; _cdecl return ; in tail loop we test last three bytes (esi and edi are aligned on dword ; boundary) tail_loop_start: test eax,eax ; eax is counter%4 (number of bytes for tail ; loop) jz short done ; taken if there is no tail bytes mov edx,[esi] ; load dword from buf1 mov ecx,[edi] ; load dword from buf2 cmp dl,cl ; test first bytes jne short difference_in_tail sub eax,1 ; counter-- jz short tail_done cmp dh,ch ; test second bytes jne short difference_in_tail sub eax,1 ; counter-- jz short tail_done and ecx,00ff0000h ; test third bytes and edx,00ff0000h cmp edx,ecx jne short difference_in_tail sub eax,1 tail_done: pop edi pop esi ret ; _cdecl return memcmp endp end
|