Arrays of structures

By now, we are fine with everything regarding access to structures and members thereof, but what if we have more than one structure of the same type? We would naturally organize them into an array of structures. Looks simple, and partially so, it is.

In order to ease the process of accessing array members, we may use an array of pointers and access each structure in the array through a kind of lookup table. In this scenario, we would simply read a pointer from the lookup table with the following:

mov  ebx, [lookup_table + ecx * 4] ; ECX contains the index into array 
; of pointers and 4 is the scale (size
; of pointer on 32-bit systems)

Having a pointer to the structure of interest, we continue the work as usual.

Our example structure is very convenient due to its size, which is only 32 bytes. Should we arrange many structures of this type into an array, we would be able to painlessly access them in an array of 134,217,727 members (on a 32-bit system), which is 4 GB in terms of occupied memory. While we would hardly need this number of strings with a maximum length of 30 bytes (or such a number of strings at all), the addressing in this specific case is very simple (again, due to the comfortable size of the structure). We still use the index in the array of structures, but, as we cannot use the scale part of SIB addressing to scale the index by 32 bytes, we need to multiply the index itself prior to accessing the array.

Let's define a macro instruction that would create such an array in the first place (building the pointer lookup table for demonstration purposes too):

macro make_strtab strtabName, [strings]
{
common
label strtabName#_ptr dword ; The # operator concatenates strings
local c ; resulting in strtabName_ptr
c = 0

forward
c = c + 1 ; Count number of structures

common
dd c ; Prepend the array of pointers with
; number of entries

forward ; Build the pointer table
local a
dd a

common ; Build the array of structures
label strtabName dword

forward
a strtabentry strings
}

The invocation of the preceding macro, with the following parameters, is as follows:

make_strtab strtabName,          ; Spaces are intentionally appended to
"string 0", ; strings in order to provide us with
"string 1 ", ; different lengths.
"string 2 ",
"string 3 "

This would result in the following arrangement of data in memory:

As you can see, the strtabName_ptr variable contains the number of structures/pointers in the array followed by the array of four pointers. Next, at strtabName, (we can choose whatever name we want when invoking the macro as long as it fits the naming restrictions), we have the actual array of four structures.

Now, should we need to retrieve the length of a string in the structure at index 2 (indices are zero based), we would modify the get_string_length procedure so that it would accept two parameters (pointer to structure array and index) in the following way:

get_string_length:
push ebp,
mov ebp, esp
push ebx ecx

virtual at ebp + 8
.structPtr dd ? ; Assign label to first parameter
.structIdx dd ? ; Assign label to second parameter
end virtual

virtual at ebx + ecx
.s strtabentry ? ; Assign label to structure pointer
end virtual

mov ebx, [.structPtr] ; Load pointer to array of structures
mov ecx, [.structIdx] ; Load index of the structure of interest
shl ecx, 5 ; Multiply index by 32
mov ax, [.s.length] ; Read the length
movzx eax, ax
dec eax
pop ecx ebx
leave
ret 8

The procedure call would be as follows:

push  2                 ; push index on stack
push strtabName ; push the address of the array
call get_string_length
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset