News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Accessing structures without assume ?

Started by Broken Sword, November 09, 2005, 11:34:26 PM

Previous topic - Next topic

Broken Sword

The dynamically allocated structure I'm working with have very complex structure, and I need another way then "assume reg: ptr" for accessing its members. Problem is that there are more then 8 substructures in my structure and I've exceed registers limit. Is there a better way in MASM to work with structures?

QvasiModo

Does this work for you?

mov eax, [edx].MY_STRUCTURE.MY_SUBSTRUCTURE.MY_OTHER_SUBSTRUCTURE.Member

Broken Sword

No, because offsets of the substructures are calculated dynamically

Tedd

It's fine to assume a register as pointing to the structure within another structure (within another, within...) without needing to give it the whole chain.

eg. for MY_STRUCTURE.MY_SUBSTRUCTURE.MY_OTHER_SUBSTRUCTURE.Member

assume edx:ptr MY_OTHER_SUBSTRUCTURE
mov eax,[edx].member


So as long as you have the address of the start of the given substructure, you can access any of its elements.
No snowflake in an avalanche feels responsible.

Broken Sword

Tedd, look, for example, to IMAGE_DOS_HEADER structure.

IMAGE_DOS_HEADER STRUCT
  e_magic           WORD      ?
  ...
  e_lfanew          DWORD      ?
IMAGE_DOS_HEADER ENDS


For example offset of this structure is in the "ibase" variable.
next step:

mov ESI, ibase
assume ESI: ptr IMAGE_DOS_HEADER


Now I can access fields of IMAGE_DOS_HEADER through ESI. But I need pointer to IMAGE_SECTION_HEADER without destroing ESI in next step:

mov EBX, ESI
add EBX, [ESI].e_lfanew
add EBX, sizeof (IMAGE_NT_HEADERS)
assume EBX: ptr IMAGE_SECTION_HEADER


Look, I'm already use two registers as structure pointers and I can't destroy them in past code.
In next step I need, e.g., pointer for IMAGE_DATA_DIRECTORY structure. I'll use third register for this, because I steel need ESI and EBX as pointers.

Is there a better way in accessing structure fields? e.g. smth like that:

assume ibase: ptr IMAGE_DOS_HEADER

and then I can use code like:
mov EBX, ibase.e_lfanew

- without registers. nice. To which code it can be compiled? Hm... maybe smth like this:

push EAX
mov EAX, ibase
mov EBX, [ibase+e_lfanew]
pop EAX


What you think?

hutch--

Robert,

There are two different situations where you use structure member, one whee you allocae the structure locally in a procedure where you sinply treat te structure member as a memory operand and the other where you pass the address of a structure to another procedure which involves a level of indirection within the called procedure.

With te second you an either use assume or you can put that address into a register to dereference it. using the two examples from the asmintro.hlp file,


    ASSUME eax:PTR RECT
    mov eax, lpRct

    mov [eax].left,   10
    mov [eax].top,    12

    mov [eax].right,  14
    mov [eax].bottom, 16

    ASSUME eax:nothing

---- or ------

    mov eax, lpRct

    mov (RECT PTR [eax]).left,   10
    mov (RECT PTR [eax]).top,    12

    mov (RECT PTR [eax]).right,  14
    mov (RECT PTR [eax]).bottom, 16

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

AeroASM

You cannot use:
mov ebx,ibase.e_lfanew

because the base address must be in a register or immediate operand, not memory.

There is no better way to work with structures in MASM. You are better off in C.

hutch--

Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Broken Sword

Hutch, but in BOTH cases I must use registers. It means, that I can operate with limited number of structures in my code. Of course, I can do

push reg
assume reg:nothing
mov reg, ptrNew_struct
assume reg: ptr NewStruct
; code which uses NewStruct
assume reg: nothing
pop reg
assume reg: ptr OldStruct


But I should use this construction before each using of NewStruct members. It's not good style - it wastes too much space.

Tedd

If you find yourself running out of registers, then you have to treat the stack as your friend :wink And/or possibly create a few local variables.
Of couse you may still have the 'unpretty' code, but hey, it's asm! :bdg

A little point on the use of assume - there's no need to "assume reg:nothing" if you're then going to assume it to something else immediately. In fact, there's no need to assume again unless you plan on using that register before you assume it to something else (considering the code as linear.)
So your example could be cleaned up a little..
push reg
mov reg, ptrNew_struct
assume reg: ptr NewStruct
; code which uses NewStruct
pop reg
assume reg: ptr OldStruct

Which is marginally more pleasing to the eye :wink
No snowflake in an avalanche feels responsible.

AeroASM

Quote from: Robert on November 11, 2005, 10:59:08 AM
It's not good style - it wastes too much space.

If you want good style and readable code then don't use asm.

MichaelW

Robert,

By "dynamically" do you mean that the structure of the substructures is variable, or that your structure is composed of a variable mix of fixed substructures? If it's the latter, then you can still use the structures as a template as QvasiModo suggested, but you would need to sum the component offsets.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    XX STRUCT
      pt1 POINT  <>
      rc1 RECT   <>
      pt2 POINT  <>
      rc2 RECT   <>
    XX ENDS   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    SZ EQU SIZEOF
    mov eax,[edx+XX.pt1.x]
    mov eax,[edx+POINT.x]
    mov eax,[edx+XX.rc1.left]
    mov eax,[edx+SZ POINT+RECT.left]
    mov eax,[edx+XX.rc2.top]
    mov eax,[edx+SZ POINT+SZ RECT+SZ POINT+RECT.top]
    mov eax, input(13,10,"Press enter to exit...")
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

Assembled code:

00401000                    start:
00401000 8B02                   mov     eax,[edx]
00401002 8B02                   mov     eax,[edx]
00401004 8B4208                 mov     eax,[edx+8]
00401007 8B4208                 mov     eax,[edx+8]
0040100A 8B4224                 mov     eax,[edx+24h]
0040100D 8B4224                 mov     eax,[edx+24h]

From WINDOWS.INC:

POINT STRUCT
  x  DWORD ?
  y  DWORD ?
POINT ENDS

RECT STRUCT
  left    dd      ?
  top     dd      ?
  right   dd      ?
  bottom  dd      ?
RECT ENDS


eschew obfuscation

hutch--

Robert,

> Hutch, but in BOTH cases I must use registers. It means, that I can operate with limited number of structures in my code. Of course, I can do

You still have not told us whether you are using the structure within the procedure you have alocated it in or whether you are passing its ADDRESS to another procedure.

A structure AS ALLOCATED is just a collection of MEMORY operands so any structure member is subject to the same rules of data movement as any other memory operand.

If you ARE passing the address of the structure to another procedure, it involves an EXTRA LEVEL OF INDIRECTION and within that procedure you must then DEREFERENCE the structure member from the passed address which can only be done in a register.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php