Hello,

i want write some string-functions:

First i try to write a SetLength proc:

SetLength proc lplpStr: DWORD, NewSize: DWORD
invoke Alloc, NewSize
mov , eax
Ret
SetLength EndP

LOCAL lpStr: LPSTR
invoke SetLength, addr lpStr, 1000h


lplpStr is a pointer on a LPSTR. Now i want dereference the pointer and allocate memory there.
The sense of this functions is to allocate mem, if lpStr is NULL else reallocate and move mem, if lpStr isn't NULL.


MfG Manuel.
Posted on 2004-02-17 12:23:23 by other
x86 doesn't have double memory indirection, so (in masm), "mov , eax" is the same as "mov lplpStr, eax" - which is modifying the pointer-to-lpStr on the stack, not the lpStr as you want it to. The following code should work.



SetLength proc lplpStr: DWORD, NewSize: DWORD
invoke Alloc, NewSize
mov edx, [lplpStr]
mov [edx], eax
ret
SetLength EndP
Posted on 2004-02-17 12:43:19 by f0dder
instructions


mov ecx, no of byte or words or dwords to move
mov esi, source memory pointer
mov edi, destination memory pointer
cld ; clear direction flag (left to right move)
rep movsd ; movsw or movsb
Posted on 2004-02-17 13:00:07 by mrgone
Hallo,


x86 doesn't have double memory indirection, so (in masm), "mov , eax" is the same as "mov lplpStr, eax" - which is modifying the pointer-to-lpStr on the stack, not the lpStr as you want it to. The following code should work.


Yes it works wonderful. Thanks for your help.


Have a nice day, Manuel.
Posted on 2004-02-17 13:13:56 by other
heh, what did that have to do with anything, mrgone? :p

Btw, you don't need cld on win32 - by default direction flag is clear. This also means that if you std, you should cld before returning - just like you must do register preservation and stack 4byte alignment.
Posted on 2004-02-17 13:18:26 by f0dder
Hello,



instructions
mov ecx, no of byte or words or dwords to move
mov esi, source memory pointer
mov edi, destination memory pointer
cld ; clear direction flag (left to right move)
rep movsd ; movsw or movsb


Thats right, but:

A lot of CPU-Opcodes are slower than write your own loop + store data.

A few month ago, i have written a StrPos-Algo, which was ca. 30% faster than the Borland pendand an has a Startindex:



function PosLeftEx(const SubStr, S: Ansistring; StartPos: Integer): Integer; assembler;
asm
{ ECX: Length(S)
EDX: Length(SubStr)
EDI: S I: Index of string (S[I])
ESI: SubStr A: Index of substring (SubStr[A])
}

TEST EAX, EAX
JE @@noWork { SubStr = nil }

TEST EDX, EDX
JE @@StrEmpty { S = nil }

PUSH EBX
PUSH EDI
PUSH ESI

MOV ESI, EAX
MOV EDI, EDX

MOV EAX, ECX { StartPosition }

CMP EAX, 0
JA @@SkipAdjust { I not in [-MaxInt..0] }
MOV EAX, 1

@@SkipAdjust:
DEC EAX { first char should be compared }
MOV ECX, [EDI-4] { Length(S) }

SUB ECX, EAX { Dec(Length(S), StartPos) }
JL @@fail { StartPos > Length(S) }

MOV EDX, [ESI-4] { Length(SubStr }
SUB ECX, EDX
JLE @@fail { Length(SubStr) > (Length(S) - StartPos) }

PUSH EDI { remember s position to calculate index }

LEA EDI, [EDI+EAX] { I := StartPos }

MOV AL, [ESI] { SubStr[1] }

JMP @@RepneScasb

@@PrepareRepeCmpsb:
MOV EBX, ECX
MOV ECX, EDX { Length(SubStr) }

@@RepeCmpsb:
DEC ECX
JZ @@found { Length(SubStr) = 0 }

MOV AH, [ESI+ECX]
CMP AH, [EDI+ECX]
JZ @@RepeCmpsb { S[I] <> SubStr[A] -> next char and Inc(I)
until S[I] = SubStr[1] }
MOV ECX, EBX
INC EDI
DEC ECX
JZ @@failWithPop { string cant be found -> end of string reached
and outer @@RepneScasb }
@@RepneScasb:
CMP AL, [EDI]
JZ @@PrepareRepeCmpsb { SubStr[A] = S[I] }
INC EDI { Inc(I) }
DEC ECX
JNZ @@RepneScasb { I <> Length(S) }
JMP @@failWithPop { I = Length(S) and S[I - 1] <> SubStr[1] }

@@StrEmpty:
XOR EAX, EAX
JMP @@noWork

@@found:
POP EDX
MOV EAX, EDI
SUB EAX, EDX
INC EAX
JMP @@exit

@@failWithPop:
POP EDX

@@fail:
XOR EAX, EAX

@@exit:
POP ESI
POP EDI
POP EBX

@@noWork:
end;



MfG Manuel.
Posted on 2004-02-17 13:34:01 by other