.386
.model flat, stdcall
option casemap:none

.data
target db "DISEASE", 0
; ^

.code
start:
lea esi, target
xor ecx, ecx
xor ebx, ebx

@@:
mov eax, [esi]
test al, al
je @F
add esi, 4
inc ecx
jmp @B
@@:
mov eax, [esi-4]
rol eax, 24
cmp al, 0 ; NULL
jne @F
inc ebx
@@:
cmp ah, 0 ; NULL
jne @F
inc ebx

@@:lea ecx, [ecx*4]
sub ecx, ebx

end start


there's one little glitch here. DISEASE = 7 char. DISEASE_ = 8 char. the problem i'm having is that it return 7 when there's 8. i've tried my best and now out of brain-cell. please don't give me the optimized verson of yours. i just want the logic of calculating the length of a string. (keep it as simple as possible, cause i want to do the optimizing myself - i like "Do it yourself!"). let me explain my logic behind this in case you're confused by the code...

first of all, i can do this by byte ptr with no problem. but it's slow! so i go for dword ptr. for example: (assume that esi = offset of target and we're searching for NULL and increase ecx by 1 if NULL doesn't exist. wait, you think adding 1 to the result gives correct answer? no! i wouldn't be posting this if it was that simple. :) )



+---+---+---+---+---+---+---+---+---+---+---+
target | D | I | S | E | A | S | E | . | | | |
+---+---+---+---+---+---+---+---+---+---+---+
^ |NULL

@@:
mov eax, [esi] ; eax = ESID (backward)
test al, al ; does al = NULL? (al=D in this case)
je @F ; jump if al = NULL
add esi, 4 ; next 4 letter
inc ecx ; increase ecx 1 by so we can times it by
; 4 later on.
jmp @B

@@:
; it's hard for me to explain from this
mov eax, [esi-4] ; point on... cause it requires alot of typing!
rol eax, 24 ; anyway, i hope you understand...
cmp al, 0
jne @F
inc ebx
@@:
cmp ah, 0
jne @F
inc ebx
@@:
lea ecx, [ecx*4]
sub ecx, ebx


try not to come up with another way. i want to stick with this logic and study it. (trashing the logic that you cannot solve is not learning).
Posted on 2001-07-23 11:26:09 by disease_2000
Despiting the fact that i consider all these optimisations
at code level, in Assembler, particulary stupid, ... here is it:




mov esi String, ecx 0

L0:
add esi 4 | inc ecx | cmp B?esi 0 | jne L0<
shl ecx 2

L0:
dec ecx | dec esi | cmp B?esi 0 | je L0<
inc ecx

hexprint ecx ; Says 9.


I can swear you that your application, if not fast enough,
will never run much quicker, (just a little bit) because of
tricks like this.


Betov.
Posted on 2001-07-23 11:59:18 by Betov
disease_2000


hi

it took me a few min but i understand your algorithm

the problem seems to be in


the first section count the number of dword that the string have
for an example we have here two dword

00403000 44 49 53 45 | 41 53 45 00 DISEASE.

this section will count the zero(null) bytes ( its a little hard to
explain and my english is not very good )


esi-4 becuase the null bytes can be only in the last dword

mov eax, ;
rol eax, 24 ; i think this is the problem u need to rotate two bytes so 16 , not 24
cmp al, 0 ; NULL
jne @F
inc ebx
@@:
cmp ah, 0 ; NULL
jne @F
inc ebx

the last section will sub between them


i notice that it will an error if the string will be something lile

db 's',0,'t','r',0
becuase it will count the 1 dword
ecx = 4
and ebx =0 because it check the lowers bytes and there arnt zero

you may want to do this check with words and not dwords, but anyway you got nice idea

eko:alright:
Posted on 2001-07-23 12:52:36 by eko
betov, that's not may goal. :) i want to understand the problem i'm facing.

eko, "this section will count the zero(null) bytes ( its a little hard to
explain and my english is not very good )
"
i understand what you mean. that's why i couldn't explain it on my original post. :)

and thank for the tip. i'll look forward for that. (i'm surprise that it only took you a few mintue... i thought that it would take you more than 15 minute!)


back to betov: i don't sit and write 32bit app. i'm more into algo study now. plus, trying to understand logic from different view.

have a great day!

-----edit msg:

eko, just check it, wow... rol eax, 24 is the problem... the reason i rotate 24 is because i only want to check middle 2 char (the last is always NULL. and there's no point of checking the first cause ....well, it's very hard to explain, but i'm sure you know what i mean!) things are fixed now thank alot!
Posted on 2001-07-23 13:58:47 by disease_2000
No, Eko, the problem is in .
There is no zero there (unless we are out, before...).

Anyway the real life way is:

mov edi String, ecx 0-1, al 0
repne scasb
sub ecx 0-2 | neg ecx


Much fast enough, and everybody can read this. If not fast
enough, the Application has to be rewritten. The better
optimisation is in the code we *do not* write (not a joke).

betov.
Posted on 2001-07-23 14:03:47 by Betov
betov, i understand what you mean. repnz scasb can check for the length. but i'm not interest in that. my main focus is on the problem i'm having. i know that my algo is not fast. (if you want superman speed, then don't write any algo. :) ) but it's part of my study. :alright:


edit:------------------
i could have use lstrlen instead which save me alot of bytes. but that's another story.
Posted on 2001-07-23 14:10:21 by disease_2000
Well, i see you point Desease. If it is just an intellectual
learning game, ok.

Again, there is a problem at first ; <<<<<<<<<<<<<<
where you prepare testing an area where there is no zero.
Should be: mov eax, (and no use because eax already
holds this.


lea esi, target
xor ecx, ecx
xor ebx, ebx
@@:
mov eax,
test al, al
je @F
add esi, 4
inc ecx
jmp @B
@@:
mov eax, ; <<<<<<<<<<<<<<<
rol eax, 24
cmp al, 0
jne @F
inc ebx ; <<<<<<<<<<<<<<<
@@:
cmp ah, 0
jne @
inc ebx ; <<<<<<<<<<<<<<
@@:lea ecx,
sub ecx, ebx


Also, as you can see your ebx can only be 0, 1, 2 (no 3).
A neighbour solution could be:


mov esi, Target
xor ecx, ecx
xor ebx, ebx
mov ebx 3
L1:
mov eax
test al, al
jz L2>
add esi, 4
inc ecx
jmp L1<
L2:
test eax eax | jz L9>
dec ebx
test ah ah | jz L9>
dec ebx
shl eax 16 | jmp L2<
L9:
lea ecx
sub ecx, ebx


though i would prefer 'mov ecx 0' instead of the stupid
'xor ecx ecx' and 'shl ecx 2' instead of 'lea ecx '.

Note (i am unsure if you got it or not...), when you load in eax
a string like:

String DB 'abc', 0

inside eax, al holds 'a', ah 'b',... i suppose you know.


Bye, Betov.
Posted on 2001-07-23 15:28:46 by Betov
betov, my code is not in optimize state. :) the reason why i have lea ecx, instead of shl ecx, 2 was because i had problem with the logic half way coding this algo.



lea ecx, [ecx*4+1], lea ecx, [ecx*4-1] <-- which was for debugging
purposes (just to make life easier while i'm coding. but once finish -
and you're right, it should be SHL ECX, 2. which i didn't thought
of it at first until you point out )


and about mov ecx, 0 : why?



33C9 xor ecx,ecx
B900000000 mov ecx,0


eko, lstrlen returns 1 if you have something like:


target db "d", 0, "i", 0, "s" ect...

the code i posted above, you can change the NULL to 0FFh or any
other char. and it will work. (problem will araise if you have:
target db "d", 0ffh, "i" and so on...)



edit:-----------
betov, i am aware of that. things will mess up if target contains only 2 char.... my code is still not perfect.
Posted on 2001-07-23 16:26:14 by disease_2000