• Welcome to Valhalla Legends Archive.
 

Hmm... Question!

Started by TheMinistered, June 02, 2003, 06:10 PM

Previous topic - Next topic

TheMinistered

Here is some useful information...

Public Sub RemoveCharacter(ByRef searchstring as String, Optional ByVal searchchar as Long = 32)

End Sub


searchstring is defined as [esp+10h]
searchchar is defined as [esp+14h]


:00000000 57                      push edi
:00000001 56                      push esi
:00000002 8B7C2410                mov edi, dword ptr [esp+10]
:00000006 8B07                    mov eax, dword ptr [edi]
:00000008 85C0                    test eax, eax
:0000000A 7450                    je 0000005C
:0000000C 8BF8                    mov edi, eax
:0000000E 8B4FFC                  mov ecx, dword ptr [edi-04]
:00000011 668B442414              mov ax, word ptr [esp+14]
:00000016 6689040F                mov word ptr [edi+ecx], ax
:0000001A D1E9                    shr ecx, 1
:0000001C 41                      inc ecx
:0000001D F2                      repnz
:0000001E 66AF                    scasw
:00000020 752A                    jne 0000004C
:00000022 4F                      dec edi
:00000023 4F                      dec edi
:00000024 41                      inc ecx
:00000025 8BF7                    mov esi, edi
:00000027 F3                      repz
:00000028 66AF                    scasw
:0000002A 7420                    je 0000004C
:0000002C 4F                      dec edi
:0000002D 4F                      dec edi
:0000002E 41                      inc ecx
:0000002F 8BD1                    mov edx, ecx
:00000031 8BDF                    mov ebx, edi
:00000033 F2                      repnz
:00000034 66AF                    scasw
:00000036 4F                      dec edi
:00000037 4F                      dec edi
:00000038 41                      inc ecx
:00000039 2BCA                    sub ecx, edx
:0000003B F7D9                    neg ecx
:0000003D 2BD1                    sub edx, ecx
:0000003F 8BFE                    mov edi, esi
:00000041 8BF3                    mov esi, ebx
:00000043 F3                      repz
:00000044 66A5                    movsw
:00000046 8BCA                    mov ecx, edx
:00000048 87F7                    xchg edi, esi
:0000004A EBDB                    jmp 00000027
:0000004C C60600                  mov byte ptr [esi], 00
:0000004F 8BC6                    mov eax, esi
:00000051 8B7C2410                mov edi, dword ptr [esp+10]
:00000055 8B3F                    mov edi, dword ptr [edi]
:00000057 2BC7                    sub eax, edi
:00000059 8947FC                  mov dword ptr [edi-04], eax
:0000005C 5E                      pop esi
:0000005D 5F                      pop edi
:0000005E 33C0                    xor eax, eax
:00000060 C20C00                  ret 000C


I have a question that is related to line 16... i'm curious... is it just me or is it moving the contents @ ax to the end of the searchstring?? could anyone tell me what's going on there?

Yoni

:00000011 668B442414              mov ax, word ptr [esp+14]
:00000016 6689040F                mov word ptr [edi+ecx], ax

It's copying 2 bytes from [esp+14], i.e. searchchar, to [edi+ecx].

:00000002 8B7C2410                mov edi, dword ptr [esp+10]
.....
:0000000E 8B4FFC                  mov ecx, dword ptr [edi-04]

Looks like ecx is the length of searchstring.
(In a BSTR, the length is stored in p-4, where p is the BSTR pointer.)

Copying 2 bytes from searchchar to [edi+ecx] is something like:
tempstring = searchstring & Chr(searchchar)
I say "tempstring" instead of "searchstring" because it doesn't seem to be updating the length ([edi-4]) until later.

TheMinistered

#2
I already know that the length of the string is stored in the BSTR header...  however, I don't agree with the following:

tempstring = searchstring & Chr(searchchar)


it's more like this... (like you said...)

searchstring = left$(searchstring, len(searchstring) -1) & chr$(searchchar)


It's actually replacing the null terminator with the search character.  Then the entire string is scanned for the character. Placing it at the end makes sure it is eventually found, I suppose in case the string length is incorrect. Because repnz would stop once ecx hit zero, normally.  Thank's for the help though, but a friend and I already figured it out :)


Yoni

What null terminator?

BSTRs don't have to be null terminated.

TheMinistered

In visual basic, they are null terminated (however, since it's unicode the null terminator takes up one word)

Skywing

Quote from: TheMinistered on June 03, 2003, 10:28 PM
In visual basic, they are null terminated (however, since it's unicode the null terminator takes up one word)
No, I think you're wrong there.  If that were true, how would all of those Visual Basic packet buffer type classes which use VB Strings to store data which includes nulls work?

Adron

They might be like msvc's std::string - there is a null terminator but it's not part of the string. VB needs to generate null terminated strings every now and then and it would make sense to keep that null terminator there for when it's needed.

TheMinistered

#7
Don't believe me skywing?  Here:

Option Explicit

Private Declare Sub RtlMoveMemory Lib "kernel32" (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Form_Load()
 Dim s As String
 Dim i As Integer
 
 s = "foo"
 
 RtlMoveMemory i, ByVal StrPtr(s) + LenB(s), 2
 Debug.Print Hex$(i)
End Sub


You can experiment to see the characters of the string by substituting 0, 2 and 4 for LenB(s).  (Thanks go out to OnError for creating the above code while I was sleeping.)

Yoni

Your test doesn't deny Skywing's message - it confirms Adron's.

BSTRs may be null-terminated for various reasons. They don't have to be. When they happen to be null-terminated (where the null isn't actually part of the string), the length doesn't include the null.

In your example, "foo" happens to be null terminated. It doesn't have to be, though.

Try something like:
Dim s As String, x As Integer
x = 1234
s = "foo"
RtlMoveMemory ByVal StrPtr(s) + 6, x, 2 ' Replace the possible null terminator with 1234
Debug.Print s ' It is not null-terminated, and yet, this doesn't crash!
x = Asc("d")
RtlMoveMemory ByVal StrPtr(s) + 6, x, 2 ' Replace the 1234 with "d"
x = 4 ' Depending on BSTR format, this might need to be 8 - forgot
RtlMoveMemory ByVal StrPtr(s) - 4, x, 1 ' Fix the length
Debug.Print s ' Should print "food"


(If I'm totally wrong here, tell me, as I wrote this directly to the forum and didn't test)

ninjaz

rofl, [vL] is yet to be proved wrong

TheMinistered

ninjaz, technically I was not wrong either.  You need to read carefully.