is it fast, or slow anyone know?
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.
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)
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)
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
.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
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...
If you want to emulate lstrcmp you'll have to do it differently.
from MSDN on lstrcmp:
I wrote this quick, haven't tested it:
eax = difference of the strings or 0 if match
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.
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
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
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
it was workin my algo now it isnt bleh!!
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
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
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
Calling strlen on both strings is unnecessary and slow.
Instead check for 0 terminator as you scan, see my code.
:alright:
Instead check for 0 terminator as you scan, see my code.
:alright:
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*.
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
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.
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?
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?
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
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
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:
Not tested.
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.
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.
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
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
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