Have a hobby parser, code generator that shells to masm32 to create a exe. Im trying to figure out the best way to do a basic string, bstr, ansi, maybe unicode, something that I can automatically resize as needed. I assume id create a pointer to a memory block to hold the string. Guess my question is should I use stack based, malloc, or heap. Im interested in any intuition on how to implement and other considerations.
This might help: https://www.quora.com/How-does-C++-implement-a-string
Have a field that contains a pointer to the buffer that contains the text and a field that contains the size of the buffer used in the "string". Can then code functions to take the address and look for the pointer and size for fields based on that structure.
THe number of bstr is limited by the size in dword of bstr_array
Quote
; #########################################################################
.386 ; force 32 bit code
.model flat, stdcall ; memory model & calling convention
option casemap :none ; case sensitive
; -------------------------------------------------------------------
; Les fichiers inclus içi ,AUCUN .lib c'est au programme utilisateur
; de les fournir
; -------------------------------------------------------------------
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\oleaut32.inc
; include \masm32\include\gdi32.inc
; include \masm32\include\user32.inc
; include \masm32\include\kernel32.inc
; include perso32.inc
; include macros.txt
; ---------------------------------------------------------
; Les PROTO sont tous regroupés dans un fichier .inc du même
; nom que la librairie .lib
; ---------------------------------------------------------
; CreateBstr PROTO :DWORD
; FreeBSTR PROTO
;UtoA PROTO :DWORD
;AtoU PROTO :DWORD
;BSTR MACRO arg
; invoke CreateBstr,SADR(arg)
; EXITM<eax>
;ENDM
;exemples de definitions externes
; EXTERNDEF Copier :PROTO :DWORD,:DWORD
; EXTERNDEF EtatMemoirePile :MEMORY_BASIC_INFORMATION
; EXTERNDEF PoriginePile:DWORD
.data
bstr_array dd 50 dup (0)
buffer db MAX_PATH dup (0)
ubuffer dw MAX_PATH dup (0)
.code
;################################################################
UtoA PROC pChain:DWORD
invoke WideCharToMultiByte,CP_ACP,NULL,pChain,\
-1,addr buffer,LENGTHOF buffer,NULL,NULL
.if eax != 0
mov edx,eax
lea eax,buffer
.endif
ret
UtoA endp
;################################################################
AtoU PROC pChain:DWORD
invoke MultiByteToWideChar,CP_ACP,NULL,pChain,\
-1,addr ubuffer,LENGTHOF ubuffer
.if eax != 0
mov edx,eax
lea eax,ubuffer
.endif
ret
AtoU endp
;################################################################
;use bstr_array in data
CreateBstr PROC pChain:DWORD
Local retour:DWORD
Local phrase[MAX_PATH]:WORD
mov eax,pChain
invoke MultiByteToWideChar,CP_ACP,NULL,pChain,\
-1,addr phrase,LENGTHOF phrase
invoke SysAllocString,addr phrase
mov retour,eax
.if eax == 0
;invoke MessageBox,NULL,SADR("FAILED"),SADR("MultiByteToWideChar"),MB_OK
jmp FindeCreateBstr
.endif
;---------------- save pointer in an array BSTR -----------------
lea edx,bstr_array
.LISTALL
mov ecx,LENGTHOF bstr_array
.NOLIST
@@:
.if dword ptr [edx] == 0
mov [edx],eax
.else
dec ecx
.if ecx != 0 ;not the end of array
add edx,4
jmp @B
.else
;failed to save bstr pointer
;invoke MessageBox,NULL,SADR("BSTR array too small"),SADR("ERREUR"),MB_OK
invoke SysFreeString,retour
mov retour,0
.endif
.endif
FindeCreateBstr:
mov eax,retour
ret
CreateBstr endp
;################################################################
;use bstr_array in data
FreeBSTR PROC uses esi
Local count:DWORD
Local retour:DWORD
mov retour,1
mov ecx,LENGTHOF bstr_array
mov count,ecx
lea esi,bstr_array
@@:
.if dword ptr [esi] != 0
mov edx,dword ptr [esi]
invoke SysFreeString,edx
mov dword ptr [esi],0
add esi,4
dec count
jnz @B
.endif
FindeFreeBSTR:
mov eax,retour
ret
FreeBSTR endp
; #########################################################################
end
Thanks for the responses, gives me a starting point to consider.
Very simple.
Quote
invoke CreateBstr,addr phrase ; phrase db "bla blate ",0 could be repeat size of bstr_array in dword(50 times)
;the bstr is in eax (or 0 if failed) and in the bstr_array
;When you have finished used them
invoke FreeBSTR ;all bstr in bstr_array are free and the bstr_array is initialized to 0
Quote from: mhmooney on July 18, 2020, 09:40:21 AMIm trying to figure out the best way to do a basic string, bstr, ansi, maybe unicode, something that I can automatically resize as needed
BSTRs in Windows are a can of worms, just try googling "bstr" and ignore the first 5 hits pointing to official Micros**t docs - an astonishing number of people have problems with them. In Windows, they are needed for COM and almost nothing else (I attach a 29-lines demo, building needs the MasmBasic library (http://masm32.com/board/index.php?topic=94.0))
But I suppose your focus was on "automatically resize as needed". Something like this?
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
Init
Let esi="A string"
PrintLine esi
Let esi="This is "+Lower$(esi)
PrintLine esi
Let esi=esi+" created "+Date$+", "+Time$
PrintLine esi
Let esi=Left$(esi, 5)+"text was"+Mid$(esi, 17)
PrintLine esi
Inkey
EndOfCodeOutput:
A string
This is a string
This is a string created 20.07.2020, 15:17:52
This text was created 20.07.2020, 15:17:52
You need macros to do that, and it's not that trivial. What exactly do you need it for?
I am just researching whether I need to do bstr, or do a c style string. It appears c style should suffice. Id like to do str1=str1+str2 and other string operators and have the code gen spit out the code needed to allocate, reallocate and free once I am ready to leave the current scope of the variable . Seems alloc$,cat$ and free$ macros do a fine job (not to mention all the other string macros available). Thanks for everyone's input
If you have a use for it, the BSTR format works OK, it done like an old PASCAL string where the character count is in the first 4 bytes and the character data is written directly after it. It is OLE string and is generally associated with BASIC style string manipulation where when you modify a string that increases its length, it re-allocates the memory and sets the length at the first 4 bytes.
You have to build a string engine to use it properly like basic which few would bother with as zero terminated strings work fine in both ANSI and UNICODE so there may be no point in doing that much work.
BSTR are much used in com.
There are small chain (or what else you want) put in a shared memory.
This allow further independants programs to communicate.
This shared memory is small and you have also to keep the bstr small.