is it fast, or slow anyone know?
Posted on 2003-04-05 22:35:45 by xkardisx
Depends on what you mean by "fast..." if you mean "optimal," i'm sure it's not, but it should be fast enough for most purposes. You could always time it by looping through it a few times, or code a similar function yourself.
Posted on 2003-04-05 23:21:15 by jademtech
It's as fast as classical string compare algorithm.
But if you want your software more robust, flexible, portable and you don't want static link with your customer library, you may want need Win32 API like lstrcmp, lstrcpy... event M$ C standard libary (contented in msvcrt.dll)
Posted on 2003-04-05 23:58:35 by nhnpresario
anyone got a source for string compare?please post! i think i have one, have to make sure it work, will post it in a bit
Posted on 2003-04-06 00:04:30 by xkardisx


.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\macros\macros.asm

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib

getstrlen proto :DWORD
comparestr proto :DWORD,:DWORD

.data
AppName db "TestApp",0
testString1 db "TEST",0
testString2 db "TEST_COW",0
strMatch db "The two strings match!",0
strDoNotMatch db "The two strings do not match!",0

.code
start:
invoke comparestr,ADDR testString1,ADDR testString2
.if ecx==1
invoke MessageBox,NULL,ADDR strMatch,ADDR AppName,MB_OK
.else
invoke MessageBox,NULL,ADDR strDoNotMatch,ADDR AppName,MB_OK
.endif

invoke ExitProcess,eax

getstrlen proc string_source:DWORD
;; len return in ecx
mov esi,[string_source]
mov ecx,-1
@@:
inc ecx
mov al,[esi+ecx]
test al,al
jne @B
ret
getstrlen endp
comparestr proc string_one:DWORD,string_two:DWORD
invoke getstrlen,ADDR string_one
push ecx
invoke getstrlen,ADDR string_two
pop eax
cmp eax,ecx
jne label_string_dont_match
inc ecx
mov esi,string_one
mov edi,string_two
label_cmp_str:
cmp ecx,-1
jz label_string_do_match
dec ecx
mov al,[esi+ecx]
cmp al,[edi+ecx]
jne label_string_dont_match
jmp label_cmp_str
label_string_dont_match:
xor ecx,ecx ;; return 0 to ecx if not match
ret
label_string_do_match:
mov ecx,1 ;; return 1 to ecx if match
ret
comparestr endp
end start
Posted on 2003-04-06 00:22:13 by xkardisx
i've only been programming in asm for like 1 week, but im pretty sure that works. i changed the the string, so far, it matches...
Posted on 2003-04-06 00:24:30 by xkardisx
If you want to emulate lstrcmp you'll have to do it differently.

from MSDN on lstrcmp:
The lstrcmp function compares two strings by checking the first characters against each other, the second characters against each other, and so on until it finds an inequality or reaches the ends of the strings.

The function returns the difference of the values of the first unequal characters it encounters. For example, lstrcmp determines that "abcz" is greater than "abcdefg" and returns the difference of z and d.



I wrote this quick, haven't tested it:

[size=12]strCmp proc uses edi esi str1:DWORD, str2:DWORD


mov edi, str1
mov esi, str2
@@: mov al, byte ptr [edi]
inc edi
mov ah, byte ptr [esi]
inc esi
sub al, ah
jnz @f
or ah, ah
jnz @b
@@: movsx eax, al
ret

strCmp endp[/size]


eax = difference of the strings or 0 if match
Posted on 2003-04-06 00:55:01 by iblis
You might want to use the standard windows convention of preserving registers so that you won't have other programs crashing (if you write a DLL or something that other programs call) and return values in eax. Also makes code a bit easier to follow :)

if you're going to testing "long" strings (~at least 16 chars), you might consider testing more than one byte at a time. The following isn't optimised - or tested... just demonstrating 4-byte compares

something like this (assuming return vals in eax):
;returns 0 on inequality, 1 on equal; assumes Str1 and Str2 are pointers to the strings
invoke GetStrLen,Str1
mov strlen1,eax
invoke GetStrLen,Str2
mov strlen2,eax

.if strlen1!==eax
xor eax,eax
ret
.endif
mov ecx,strlen1
shr ecx,2

mov esi,Str1
mov edi,Str2

sub esi,4
sub edi,4
@@:

mov edx, ;compare 4 bytes at a time
cmp edx,
jne Unequal
dec ecx
jnz @B

and eax,3 ;compare last few bytes
add esi,strlen1 ;move to end of string
add edi,strlen1
@@:
mov edx,
cmp ,edx
jne Unequal
dec eax
jnz @B

inc eax
ret

Unequal:
xor eax,eax
ret
Posted on 2003-04-06 00:58:58 by jademtech
it was workin my algo now it isnt bleh!!
Posted on 2003-04-06 00:59:11 by xkardisx
ah i figure out why it didnt work

i had tried to use lea with a dword, i sort of made the proc at last minute before postin, i had tested with lea/, etc.

i'm not looking to redistribute anythin really, i just tryin to find a faster algo for string comparision. i used the lstrcmp and it was extremely slow in my program :x
Posted on 2003-04-06 01:05:42 by xkardisx


getstrlen proc string_source:DWORD
;; len return in ecx
mov esi,[string_source]
mov ecx,-1
@@:
inc ecx
mov al,[esi+ecx]
test al,al
jne @B
ret
getstrlen endp
comparestr proc string_one:DWORD,string_two:DWORD
invoke getstrlen,string_one
push ecx
invoke getstrlen,string_two
pop eax
cmp eax,ecx
jne label_string_dont_match

mov esi,string_one
mov edi,string_two
label_cmp_str:
cmp ecx,-1
je label_string_do_match
dec ecx
mov al,[esi+ecx]
cmp al,[edi+ecx]
je label_cmp_str
label_string_dont_match:
mov ecx,0 ;; return 0 to ecx if not match
ret
label_string_do_match:
mov ecx,1 ;; return 1 to ecx if match
ret
comparestr endp
end start
Posted on 2003-04-06 01:06:15 by xkardisx
Calling strlen on both strings is unnecessary and slow.
Instead check for 0 terminator as you scan, see my code.

:alright:
Posted on 2003-04-06 01:12:24 by iblis
Well... In case you don't know the return value should be stored in eax and not ecx. Remember to preserve edi,esi and ebx.

My dab into coding my own verison. Not too sure whether it is *faster* or *smaller*.



strcmp proc string1:DWORD, string2
pushad
mov esi,string1
mov esi,string2
xor ecx,ecx
@@:
mov al,[esi+ecx]
or al,al
jz matched
sub al,[edi+ecx]
jnz notmatched
inc ecx
jmp @B
popad
xor eax,eax
ret
notmatched:
popad
xor eax,eax
inc eax
ret
strcmp endp
Posted on 2003-04-06 01:15:46 by roticv
Also note that you may find it beneficial to have your strcmp return the difference of the two strings, should you ever have a situation sometime in the future where you would want to do string sorting or other such things.
Posted on 2003-04-06 01:28:45 by iblis
i know most api manipulate eax, and most ppl code stuff to return eax. the reason i returned ecx its maybe just habit, i like to keep #s in ecx ;\ also, from time to time, i come across an api who screw up my ecx value, which cause me having to push and pop values off the stack

i guess the code i submitted was merely for my own program

although i havnt tested my function with the lstrcmp, i realize now that when implemented it in my program, they are both slow ;\

as far as the strength len function.. i guess you are right, but i figure since i would be using the length of the two string, i might as well call them, and if they arnt the same, they automatically don't match (checks for a null char as well i think)


getstrlen proc string_source:DWORD
;; len return in ecx
mov esi,
mov ecx,-1
@@:
inc ecx
mov al,
test al,al
jne @B ;; check for null, if none, repeat
ret
getstrlen endp

well, if urs work fine, i cant complain hehe..
it appears to be a lot smaller for sure

and at this moment, i see what you mean. kill 2 birds with one stone. right?
Posted on 2003-04-06 01:52:53 by xkardisx
mov esi,string1
mov esi,string2

?? i take it u meant mov edi,string2

:P just notice dat, i am really comparin all the functions y'all postin need to make my code faster ;] size aitn a problem, speed is
Posted on 2003-04-06 01:59:24 by xkardisx
I just tested it and it does work.
But yes if you are going to need the string length anyway, then by all means make use of it. ;)

Perhaps something like:

[size=12]

.data
str1_len dd 0
str2_len dd 0

.code
[...]
mov edi, str1
mov esi, str2
invoke strlen, edi
mov str1_len, eax ;save for later
mov ecx, eax
invoke strlen, esi
mov str2_len, eax ;save for later

cmp ecx, eax
mov eax, 0
jne @f
repz cmpsb
or ecx, ecx
setz al
@@: ret
; eax = 0 (no match)
; eax = 1 (match)[/size]


Not tested.
Posted on 2003-04-06 03:11:35 by iblis

size aitn a problem, speed is


If speed is what you're after take a look at jademtech's post, as he uses strlen also and shows how to do multibyte compares which would speed things up on long strings.

If blazing speed is what you're after then look into using MMX and such.


Edit: Also check Hutch--'s MASM lib. It might have a fast strcmp you can use. I've never used masmlib so I don't know for sure.
Posted on 2003-04-06 03:18:41 by iblis
Well you can do



strlen proc
;esi = offset of string
xor eax,eax
stc
sbb ecx,ecx
repne scasb
xchg eax,ecx
neg eax
ret
strlen endp
Posted on 2003-04-06 03:23:30 by roticv
heh, i didnt mean i needed the len of the string for u later used..

i meant, my function checks if the len are the same, if so, then it will check if the string is the same. and then, instead of havin to check for another null char when comparing the two bytes, since i already did that, since both the string are the same length, i just check if they are the same, and if they arnt, they arnt ya know what i mean, i hope u understand that w/o a period to make sense of things. ;x

if length=same then check if string s are same
end of string and bytes are still the same..still? then strings are same
if byte=same
go next byte
check again
else
strings are not same
end if
else
strings are not same
end if

i know u dun need me to explain ;p
Posted on 2003-04-06 03:36:20 by xkardisx