This one below is one I am playing with at the moment, it is testing up OK at the moment. It compares any 2 addresses for the length set in the ln parameter and exits on mismatch. I think some of the traditional ones exit with the byte count for the mismatch but this one does not. It can probably be made a bit faster if it is necessary but I doubt that there is much to gain from doing it. Regards, hutch@pbq.com.au

; ########################################################################

cmpstr proc lpStr1:DWORD,lpStr2:DWORD,ln:DWORD

    push esi
    push edi

    mov esi, lpStr1
    mov edi, lpStr2
    mov ecx, ln
    cmp ecx, 4
    jb bLoop
    shr ecx, 2              ; divide by 4
    xor edx, edx

  @@:
    mov eax, 
    cmp eax, 
    jne Mis_Match
    add edx, 4
    dec ecx
    jnz @B

    mov ecx, ln
    and ecx, 3
    cmp ecx, 0
    je OK_Match
    add ecx, edx

  bLoop:
    mov al, 
    cmp al, 
    jne Mis_Match
    inc ecx
    cmp ecx, ln
    jne bLoop

  OK_Match:
    mov eax, 1
    jmp cmpQuit

  Mis_Match:
    xor eax, eax

  cmpQuit:
    pop edi
    pop esi

    ret

cmpstr endp

; ########################################################################

Posted on 2001-06-01 05:40:00 by hutch--
Since your only concerned with equality/inequality you can compare the bytes in the string in any sort of order you want. While I'll admit that your algorithm above is straight-forward and easy to read, here is another solution:
; ########################################################################

cmpstr proc lpStr1:DWORD,lpStr2:DWORD,ln:DWORD

    push esi
    push edi

    mov ecx, ln
    mov esi, lpStr1
    mov edi, lpStr2
    and ecx, -4      ; DWORD align
    jmp xLoopStart

dLoop:
    mov eax, 
    cmp eax, 
    jne Mis_Match
dLoopStart:
    sub ecx, 4
    ja dLoop

    mov ecx, ln
    and ecx, -4
    add esi, ecx
    add edi, ecx

    mov ecx, ln
    and ecx, 3
    jmp bLoopStart

  bLoop:
    mov al, 
    cmp al, 
    jne Mis_Match
bLoopStart:
    dec ecx
    ja bLoop

  OK_Match:
    mov eax, 1
    jmp cmpQuit

  Mis_Match:
    xor eax, eax

  cmpQuit:
    pop edi
    pop esi

    ret

cmpstr endp
The loops can easily be converted to string instructions if one wishes to make a size optimized version. And I didn't use edx, so the registers could be renamed and save a push/pop pair; or improve the calculation in the center. This is just a quick hack from work. Please, point out errors I've made. :) I think this is slower. :) Oh, the 'and ecx, -4 ; DWORD align' assumes that the two strings are DWORD aligned. This message was edited by bitRAKE, on 6/1/2001 11:41:10 AM
Posted on 2001-06-01 11:26:00 by bitRAKE
It's a shame that repne cmpsb doesn't work differently - then this algo would hardly be needed. :) Another version just for fun:

cmpstr proc lpStr1:DWORD,lpStr2:DWORD,ln:DWORD
    push esi
    push edi

    mov esi, lpStr1
    mov edi, lpStr2
    mov eax, ln
    jmp xLoopStart

  dLoop:
    cmpsd
    jne Mis_Match
  dLoopStart:
    sub eax, 4
    ja dLoop

    add eax, 4
    jmp bLoopStart

  bLoop:
    cmpsb
    jne Mis_Match
  bLoopStart:
    dec eax
    ja bLoop

  OK_Match:
    mov eax, 1
    jmp cmpQuit

  Mis_Match:
    xor eax, eax

  cmpQuit:
    pop edi
    pop esi

    ret
cmpstr endp
...or in a macro...

STRCMP MACRO str1, str2, len
  LOCAL Loop, intoLoop, StrNE

    mov esi, str1
    mov edi, str2
    mov eax, len
    jmp intoLoop
Loop:
    cmpsb
    jne StrNE  ;z flag is clear
intoLoop:
    dec eax
    ja Loop
    inc eax    ;set z flag!
StrNE:
  ENDM
...use it like this...

    STRCMP MyString1, MyString2, 25
    jne TheyAreNotEqual
Posted on 2001-06-01 13:43:00 by bitRAKE