I thought someone may like this, its a single memory allocation that stores both the array of pointer and the data stored in the same block of memory. Its plussed are that its fast to get going and maintains 4 byte alignment for each array member, its minuses are it has no bounds checking and does not store the member count.
IF 0 ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
Build this template with "CONSOLE ASSEMBLE AND LINK"
ENDIF ; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
fixed_array PROTO :DWORD,:DWORD
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL hArr :DWORD
LOCAL acnt :DWORD
push ebx
push esi
push edi
mov acnt, 8192
mov hArr, rv(fixed_array,acnt,12)
mov esi, hArr
xor edi, edi
xor ebx, ebx
; --------------------------------------------
; write ascending hex strings to array members
; --------------------------------------------
@@:
fn szCopy,uhex$(ebx),[esi] ; write string to address in ESI
add esi, 4 ; set address to next pointer
add ebx, 1 ; increment number counter
add edi, 1 ; increment loop counter
cmp edi, acnt ; compare it to array count
jl @B ; jump back if lower
mov esi, hArr
xor edi, edi
; ---------------------------------
; display the ascending hex strings
; ---------------------------------
@@:
print [esi],13,10
add esi, 4
add edi, 1
cmp edi, acnt
jl @B
invoke GlobalFree,hArr ; deallocate memory allocated in the "fixed_array" algo
pop edi
pop esi
pop ebx
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 16
fixed_array proc cnt:DWORD,blen:DWORD
; allocate a zero filled array with pointers to members
; at the front and member storage after the pointers
; array member storage aligned to a minimum of 4 bytes
; when the array is no longer required the memory should be
; de-allocated using the GlobalFree() API function call
; virtues (1) fast allocation of zero filled fixed array with aligned members
; (2) single memory allocation for both pointers and data storage
; vices (1) no bounds check to member length
; (2) array count is not stored in the array
; the pointer array and the data storage is layed out with this logic
; ----------------------------------------------------------------
; | ptr1 | ptr2 | ptr3 | data1 | data2 | data3 | etc ....
; ----------------------------------------------------------------
; each pointer occupies 4 bytes, each data storage is
; the nominated size rounded up to a 4 byte boundary.
push esi
push edi
mov edi, [esp+16]
add edi, 3 ; align blen up to next 4 byte boundary
and edi, -4
mov esi, [esp+12]
add esi, esi ; mul cnt by 4
add esi, esi ; store pointer array length in ESI
mov ecx, [esp+12] ; calculate length required
mov eax, edi
imul ecx ; multiply cnt by blen to get data storage size
add eax, esi ; add pointer array length
push eax
push GMEM_FIXED or GMEM_ZEROINIT ; allocate fixed memory
call GlobalAlloc
mov edx, eax ; store memory address in EDX
mov ecx, eax
add ecx, esi ; add the length of the pointer array to ECX
mov esi, [esp+12]
align 4
@@:
REPEAT 3
mov [eax], ecx ; write each data storage member to pointer array
add eax, 4 ; next pointer
add ecx, edi ; add blen for next data storage
sub esi, 1
jz @F
ENDM
mov [eax], ecx ; write each data storage member to pointer array
add eax, 4 ; next pointer
add ecx, edi ; add blen for next data storage
sub esi, 1
jnz @B
@@:
mov eax, edx ; return the memory start address
pop edi
pop esi
ret 8
fixed_array endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Thanks Steve.
I really like these examples of yours.
They always make me learn something interesting.
Frank