Is this code right for calculating the string length? The length minus the null terminator should end up in eax.




.data
string db "test",0

.code

lea eax, string

xor edi, edi
loop_top: cmp [eax+edi], 0
inc edi
jnz loop_top
mov eax, edi
ret
Posted on 2003-04-10 14:43:48 by jInuQ
Exchange the roles of eax and edi, you won't need that move at the end.
Posted on 2003-04-10 15:31:24 by Tomasz Grysztar
I was now actually think of not making the the eax, edi change and just leave the results in edi.
Posted on 2003-04-10 21:07:55 by jInuQ
you might want to search around on the board. Unless they went in the "spring cleaning", there's some highly optimized string length algorithms around here.
Posted on 2003-04-11 01:52:40 by f0dder
I have found some ,but unless I want to go through contacting the authors to see if there source is public domain or other wise, which I don't really feel like right now, it would make my fasm library kind of worthless to have to rip out code later.

And besides that I am mainly shooting right now for simple code. Nothing that takes hours to understand.

Tho' I am grateful for the help. 8^)
Posted on 2003-04-11 02:22:24 by jInuQ
The algo will not work because the INC instruction destroys the Z flag!

Feel free to use anything I post:
.data

string db "test",0

.code

lea esi, string

or eax, -1
loop_top:
inc eax
cmp [esi+eax], 0
jnz loop_top
ret
...it's not fast, but not too hard to understand either.
StrLen:

or eax, -1
loop_top:
inc eax
cmp [esi+eax], 0
jnz loop_top
ret

StrCat:
mov esi, String1
call StrLen
lea edi, [esi + eax]
mov esi, String2
call StrLen
lea ecx, [eax+1] ; copy null byte, too
rep movsb
ret
; edx = array of strings

; esi = string to add to
MultiStrCat:
call StrLen
lea edi, [esi + eax]

_0: mov esi, [edx]
add edx, 4
test esi, esi
je _x

call StrLen
mov ecx, eax
rep movsb
jmp _0

_x: mov BYTE PTR [edi], 0
ret
Posted on 2003-04-11 03:14:43 by bitRAKE
Hi!,

I'm not an expert in these matters.

But I found this C code in Dan J. Bernstein's (the author of qmail) library.



unsigned int str_len(const char *in) {
register const char* t=in;
for (;;) {
if (!*t) break; ++t;
if (!*t) break; ++t;
if (!*t) break; ++t;
if (!*t) break; ++t;
}
return t-in;
}


The string scanning loop is unrolled 4 times. Compiling the above
code with gcc-3.3 -O6 -S I got this asm version (pardon me for presenting AT&T syntax ;) )



.globl str_len
.type str_len,@function
str_len:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl %edx, %eax
.p2align 4,,15
.L2:
cmpb $0, (%eax)
je .L3
incl %eax
cmpb $0, (%eax)
je .L3
incl %eax
cmpb $0, (%eax)
je .L3
incl %eax
cmpb $0, (%eax)
je .L3
incl %eax
jmp .L2
.L3:
popl %ebp
subl %edx, %eax
ret


BTW, the api style of Dan Bernstein is worth following. Its very clear and unambiguous unlike libc.

Checkout his site: http://cr.yp.to

cheers,
-Krish
PS: iirc, the watcom (now, openwatcom) compiler's rtl also has highly optimized routines worth checking out .
Posted on 2003-04-12 11:31:20 by krish
Thanks for the info bitRake. Works good. Any thing special you want me to put in the about of the library?

krish - thanks for the c, will have to compile with out the optimizing turned on. First version is going to be the simple version.
AT&T is okay, makes you think. 8^)
Posted on 2003-04-12 18:14:45 by jInuQ
okay, this is kinda on the same string subject. Let me know if this code would be way too slow or any other problems.

Be aware that this code is thinking StrLen returns the length in edi.



StrCat:
mov esi, string1
call StrLen
lea eax, string1
add eax, edi
mov esi, string2
call StrLen
xor ebx, ebx
lea edx, string2
loop_start:
mov [eax + ebx], [edx + ebx]
inc ebx
dec edi
cmp edi, 0
jnz loop_start
mov byte [eax + ebx], 0
ret
Posted on 2003-04-12 18:32:04 by jInuQ
jInuQ, you can just use the StrCat I post above - read an asm reference to learn what the instructions do. My name is "Rickey Bowers Jr. (bitRAKE)" - if you put may name anywhere that would be very kind.

krish, if your going to unroll a loop that is not the code to use. Please, search the board if you wish to find strings quickly in x86 - there are several algorithms for different expected average lengths, on different target processors.
Posted on 2003-04-12 19:57:05 by bitRAKE
I already include your strcat in the source for the library, I was just kinda interested in know if the one I had done would work.

I will put you name at the top of the file with the StrLen and StrCat functions and when I do a contributor section it will go there.
Posted on 2003-04-12 20:16:52 by jInuQ
jInuQ, algorithm looks good. I've commented below:
StrCat:

mov esi, string1
call StrLen
lea eax, string1
add eax, edi
mov esi, string2
call StrLen
xor ebx, ebx
lea edx, string2
loop_start:
[COLOR=green]; This is not an x86 instruction - are you using a FASM macro?[/COLOR]
mov [eax + ebx], [edx + ebx]
inc ebx
dec edi
[COLOR=green]; This instruction is not needed DEC will set/clear the Z flag.[/COLOR]
; cmp edi, 0
jnz loop_start
mov byte [eax + ebx], 0
ret
Posted on 2003-04-12 23:54:49 by bitRAKE
Okay, I think you need to be a little more specific for me this week 8^). Which instruction is not x86?
Posted on 2003-04-13 01:31:25 by jInuQ
This one isn't a single instruction:
    mov [eax + ebx], [edx + ebx]
Posted on 2003-04-13 03:41:02 by bitRAKE
Would it not be similar to



lea edi, [esi + eax]


which you used in your MultiStrCat function?

What I was trying to do is get both strings to increment together.
Posted on 2003-04-13 03:45:13 by jInuQ
LEA stands for Load Effective Address -- no data is moved in memory; an address calculation is done to obtain a pointer to a place in memory. Often this instruction is used to do simple math without effecting the flags.
	lea	edi, [esi + eax]
The above instruction says to calculate the address of the memory location at and put that address into EDI. Similar to:
mov edi, esi

add edi, eax
...but one instruction, and doesn't effect the flags.

In my algo, REP MOVSB is doing all the work - move ECX bytes from ESI to EDI, and add ECX to both ESI and EDI! For your algo, you would have to use a temporary register to store the data, ex:
loop_start:

mov cl, [edx + ebx]
mov [eax + ebx], cl
inc ebx
dec edi
jnz loop_start
There is much experience going into the selection of instructions and register usage.
Posted on 2003-04-13 04:23:10 by bitRAKE
jInuQ,

You can use the strlen and strcat functions provided by the C run-time DLLs.

http://www.asmcommunity.net/board/showthread.php?s=&postid=70951&highlight=strcat.msg70951

Regards,

Vortex
Posted on 2003-04-13 07:08:14 by Vortex
Vortex,

They are SLOW!!!
It will be better to follow f0dder's suggestion:
"you might want to search around on the board.
Unless they went in the "spring cleaning",
there's some highly optimized string length algorithms around here."

Regards,
Lingo
Posted on 2003-04-13 10:30:46 by lingo12
Dear amigo lingo12,

Really,I wonder:whenever you use the strcat function,do you need of
optimized functions? There are two situations:

a)To get a short code:use C run-time DLLa
b)To get a speedy code:use optimized algos.

Think about it... :)

Regards,

Vortex
Posted on 2003-04-13 11:13:22 by Vortex
lingo12: for some examples of fast asm code check this out: http://www.azillionmonkeys.com/qed/asmexample.html

cheers,
-Krish
Posted on 2003-04-13 11:18:04 by krish