Hi @all...
I have defined a structure this way:


EXT_LOADER struct
sExtension db 4 dup(?)
sLoader db 12 dup (?)
EXT_LOADER ends


I have declared in the .data? section:


Loaders EXT_LOADER 64 dup (<>)


In the code section I address its fields by manual calculation of the address. For example if I have to access the .sLoader of the 5th structure I do 16 * (5-1) + 4.
Is there a simpler way to access it, something like in C?

Loaders[5].sLoader

It gives me errors!

Thanx!

Sincerely,
Daniel
Posted on 2001-12-21 12:12:45 by dguzz
I believe you can do it a couple of ways, but the way I often do it is:

lea ebx, Loaders

mov edx, 4 ; << Fifth item
shl edx, 4 ; since its 16 bytes long!

mov (EXT_LOADER PTR [ebx + edx]).sLoader, 1234h


I have an exam today in this stuff and learned that there is also a "Based Relative Plus Index" addressing mode for Intel systems (( Pretty screwy name but it goes like this ))

mov ARRAY,DX

if ARRAY = 1000H, BX=0300H, SI=0200H

then this will move DX to address 1500H.

This is the way your trying to attempt this. Except the 'SI' if being equated as ".sLoader", BX=5, and ARRAY = Loader.

This is fine and well, but the reason your getting errors is because the program doesnt know your intentions. you assume 5 means (5th structured occourance), but the compiler sees this as "ADD 5". So you actually locating:

1000h : Base addrss of "Loader" (just a number)
+ 05h : [5] term
+ 04h : .sLoader is the 4th byte in the structure
=====================================
1009h >> YOUR STILL within the first 16 bytes!!!

This is why you get errors.. your still only messing with the first structure!

To correct your way of doing things simply add:

mov Loader[ 4 * SIZEOF EXT_LOADER ].sLoader, 1234h ; this is the 5th item

Anywho.. there is a bit more than i expect you wanted..

Hope it helps.
:alright:
NaN
Posted on 2001-12-21 12:48:45 by NaN
Thanx NaN,
it surely helps... and thanx for the very complete answer.

I coded the sma eway you exampled in the first part, but I think I'll translate to the last part of your message all of my code.

Thanx again NaN

Sincerely,
Daniel
:alright:
Posted on 2001-12-21 14:37:26 by dguzz
Nope problem.. glad to help :)

(( I learned a bit there too :) ))

NaN
Posted on 2001-12-22 01:08:23 by NaN
... and I didn't realize that my problem was explained not so good. Reading the answer I was very happy because it effectively replied my question, but my question is just a little bit different.

Still valid the struct definition and the declaration, I need to access a field in it (both the first and the second in different parts of the code), but the numer of which structure I have to access is in EBX (it was the 5 in the preceding post) and is returned by another proc.
So I used this way:

dec ebx
shl ebx, 4 ; EXT_LOADER is 16 bytes long
lea edi, Loaders

This way I get the starting address of the structure number EBX.

I cannot use

lea edi, Loaders

because masm won't compile.

Now the question is the same: is there a simpler way to access it, something like in C?

Loaders.sLoader

Thanx again and please excuse me for not having explained my problem well enoguh (I was very tired)...

Sincerely,
Daniel
Posted on 2001-12-22 04:35:36 by dguzz
Well ASM compilers/assemblers will help you on structures but will not help you with arrays. The reason is clear: this is one of the main jobs for high level compilers (be it C or others), in ASM this is a job for hummans ...

Indexing into arrays offten needs you to calculate the base addres of element . This can be as simple as a multiplication with the size of the element and then adding the base addres of array element zero.

Hummans and some times compilers try to optimise this calculations in many ways:
- use power of 2 for elements size:
like 16,32,64,128,256 etc, this will make the multiplication into a shl instruction wich is much faster than a multiplication

-incremental parse the array:
there is no need for a multiplication when you know that you move from one element to the other, you can just add the size of one element on each loop

given those options and many others assemblers do not know what to do, and IMHO you know it better!

So IMHO the most simple way to do it is like this:
;----------------------------------------
;define one array element
;----------------------------------------
Array_element STRUC
field01 dd ?
field02 dw ?
field03 db ?
Array_element ENDS
;-----------------------------------------
; define 1000 elements array
;-----------------------------------------
Array_base Array_element 1000 dup (<?>)

;----------------------------------------------
;calculate base addres of element N
;----------------------------------------------
mov esi,offset Array_base
mov eax,N
mov ebx,SIZE Array_element
mul eax,ebx
add esi,eax
;----------------------------------
; start updating element N
;----------------------------------
mov ,ecx ;dword
mov word ptr ,cx ;word
mov byte ptr ,cl ;byte
;------------------------
; etc etc
;----------------------

As a speed optimization if you have 16 bytes array elements:

;--------------------------------------------------------
;calculate faster base addres of element N
;--------------------------------------------------------
mov esi,offset Array_base
mov eax,N
shl eax,4
add esi,eax
;-----------------------------------


Of course you can make MACROs out of those basic things and then you will be able to acces your array allmost like in C.

But i am not a macro guru ...

It is important that you realise that every time you write in C:

Array.filed01=some_data;

the compiler generates those kind of instructions for you... by the quality of this generated code it will depend the speed of your program ...

For example if you have multiple such instructions in your code (all with same index N) some compilers will generate multiply code each time...a thing that will never cross my mind because there is no reason to change the esi pointer until we move to the next/other N...isnt it?

Besides if i need (for filter graphic effects) i will temporary only add SIZE ARRAY_element to esi this time and multiply next time...etc


That is why i like to do it myself and in ASM ;)
Posted on 2001-12-22 09:22:06 by BogdanOntanu
Hi BogdanOntanu,
thanx for the wide review of the argument...

I created my struct 16 bytes long just to use shl ebx, 4 as you can see from my reported code. I also use ofetn a few tricks to optimize speed, but I was wondering id there was a more self-explicative way to address array of structures. This is because I'll release the code (it is part of what will be an Image Editor) and make it modifiable by anyone who wants to optimize it or to develop a plugin for it (even though the plugin interface is quite completed and does not need the source code of the main application).

Anyway... thanx for the long answer.

Sincerely,
Daniel
Posted on 2001-12-22 12:15:55 by dguzz
I don't have any expertise or talent in the field
of Macros, but this seems to be the place where
a well written macro would take care of indexing
into an array. Would it be possible +/or
practical?:confused:

farrier
Posted on 2001-12-23 05:11:38 by farrier
The reason your getting errors is because there are two arrays.

Try this:

; zero to first byte of sExtension in sixth item in array.
mov Loaders[5].sExtension[0],0

shl eax, 4 ; no macro needed...
mov Loaders.sExtension[2],0

Chapter 5 - Defining and Using Complex Data Types
Posted on 2001-12-23 11:32:19 by bitRAKE
bitRAKE,

That looks like the way to do it. Even better
than a Macro;) But one thing confuses me. I'll
use the word index to refer to the numbers inside
the []'s, just like indeces in a C array. Is that
still the proper term here?

One thing confused me about your post though.


shl eax, 4 ; no macro needed...
mov Loaders.sExtension[2],0


By using shl eax, 4 you are multiplying the
previous index for a Loaders struc by 16. I would
have thought that to access the next Loaders
structure, you would simply increment the index
for Loaders. For example:

To access element 3 of Loaders and fourth byte of
sLoader you would use Loaders[2].sLoader[3] and
then to access element 4 of Loaders and fourth
byte of sLoader Loaders[3].sLoader[3] Just
increasing from 2 to 3 for the Loaders index will
access 16 bytes beyond the previous reference. Is
that right, that the index for Loaders only needs
to be incremented by 1 and not 16?

Thanks,
:confused:
farrier
Posted on 2001-12-24 06:16:31 by farrier
If you use a register, MASM doesn't know what to assume. So, MASM assumes that you know what your doing. :)
mov [eax*16],0 ; this will produce an error

There is no instruction for what you suggest, but the following will work because there is an addressing mode that matches.
ArrayTest dd 64 dup (?)

mov ArrayTest[eax*4],0
You can multiply a register by 2, 4, or 8 in the addressing mode, but you must explicitly state that in your access of the array. I don't think it would be consistent for MASM to automatically adjust accesses to arrays of 2,4,8 in size and not do so for larger arrays. Leaving it to the programmer is more consistent.

For the example in the above post, this also works:
shl eax, 1 ; no macro needed... 

mov Loaders[eax*8].sExtension[2],0
shr eax,1 ; now it's back to original value
Posted on 2001-12-24 11:32:16 by bitRAKE
To BogdanOntanu,

I use the same technique for my structures as you
use in your example below.

But I have a problem.
I can not use the following instruction:
mov , ecx

I always get an undefined symbol for fildd01
when I assemble.
So I have to compute the offset into the structure
and use:
eax = offset
mov , ecx

Is there a way to tell the assembler that field01
belongs to esi?


;----------------------------------------
;define one array element
;----------------------------------------
Array_element STRUC
field01 dd ?
field02 dw ?
field03 db ?
Array_element ENDS
;-----------------------------------------
; define 1000 elements array
;-----------------------------------------
Array_base Array_element 1000 dup (<?> )

;----------------------------------------------
;calculate base addres of element N
;----------------------------------------------
mov esi,offset Array_base
mov eax,N
mov ebx,SIZE Array_element
mul eax,ebx
add esi,eax
;----------------------------------
; start updating element N
;----------------------------------
mov ,ecx ;dword


Thanks,

Ewayne
Posted on 2001-12-29 23:07:48 by Ewayne
Ewayne, there are several methods in MASM:
mov [esi].Array_element.field01,ecx
...or...
ASSUME esi:PTR Array_element

mov [esi].field01,ecx
ASSUME esi:NOTHING
...or...(of course there is a way with macros :))
OPTION:DOTNAME

.field01 EQU <[0]> ; okay, I'm not seriously suggesting you use this :)
mov [esi].field01,ecx
Or, were you talking about in TASM?

p.s. I'd like to say that your code examples have been some of the most helpful to me getting over the windows learning curve. Thank you.
Posted on 2001-12-30 02:07:17 by bitRAKE
To bitRAKE,

I'm using MASM.


code:

mov .Array_element.field01,ecx

I don't want to use the structure name in the statments.


code:

ASSUME esi:PTR Array_element
mov .field01,ecx
ASSUME esi:NOTHING

I know the assume works, but thats an extra step.


code:

OPTION:DOTNAME
.field01 EQU <[0]> ; okay, I'm not seriously suggesting you use this
mov .field01,ecx

I don't like to use macro's if I don't need to.

My problem is that in my current project I have
many different structures in many arrays and I
would like to be able to load the address of the
structure in the array and just do a:

mov , ecx

Right know I have a routine that computes the
offset into the structure and add that to my
structure address.

p.s. Thanks for your last comment.

Thanks again,

Ewayne
Posted on 2001-12-30 08:39:03 by Ewayne