News:

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

Structures

Started by Astro, July 24, 2009, 03:00:10 AM

Previous topic - Next topic

Astro

 :dazzled:

Could someone give me a Structures 101 please? I've looked at the help file that came with MASM but I'm still none the wiser.

I need to nail this as I'm going to need them quite soon for USB enumeration, and there are lots of them.

Best regards,
Astro.

ecube


this should be all the structs you need, been awhile since I messed with USB devices

DBT_DEVICEARRIVAL    equ 32768
DBT_DEVICEREMOVECOMPLETE   equ 32772
DBT_DEVTYP_DEVICEINTERFACE equ 5
DBT_DEVTYP_VOLUME          equ 2h

GUIDX STRUCT
    Data1               DWORD ?
    Data2               DWORD ?
    Data3               DWORD ?
    Data4 byte 7 dup(?)           
GUIDX ends

DEV_BROADCAST_HDR STRUCT
    dbch_size           DWORD ?
    dbch_devicetype     DWORD ?
    dbch_reserved       DWORD ?
DEV_BROADCAST_HDR ends

DEV_BROADCAST_DEVICEINTERFACE STRUCT
    dbcc_size           DWORD ?
    dbcc_devicetype     DWORD ?
    dbcc_reserved       DWORD ?
    dbcc_classguid      _GUID <>
    dbcc_name           byte 83 dup(?)
DEV_BROADCAST_DEVICEINTERFACE ends

DEV_BROADCAST_VOLUME STRUCT
    DBCV_Size           DWORD ?
    DBCV_DeviceType     DWORD ?
    DBCV_Reserved       DWORD ?
    DBCV_UnitMask       DWORD ?
    DBCV_Flags          DWORD ?
DEV_BROADCAST_VOLUME ends


donkey

A structure is simply a memory template that represents a block of contiguous memory of a specific size and has a number of preset divisions labeled within it. For example say a function outputs the bounding coordinates of a rectangle, there are 4 coordinates necessary to describe a rectangle, top, left, width and height so that would require 16 bytes. Now since the ordering of the coordinates is always the same you can represent the data set as follows:

RECT =
bytes 0..3 top
bytes 4..7 left
bytes 8..11 width
bytes 12..15 height

or more simply

RECT STRUCT
   top DWORD
   left DWORD
   width DWORD
   height DWORD
ENDSTRUCT

Now lets say that in some cases a function will output right and bottom instead of width and height. In order to make your code more readable and understandable you might want to include the possibility of using those labels as well without actually needing to define a new structure. In that case you would use a UNION. In its simplest form a union is two labels that begin at the same address within the structure, since they begin at the same address they occupy the same space and so are necessarily mutually exclusive. The size of a union is always the size of its largest member.

RECT STRUCT
   top DWORD
   left DWORD
   UNION
       width DWORD
       right DWORD
   ENDUNION
   UNION
       height DWORD
       bottom DWORD
   ENDUNION
ENDSTRUCT

In the previous structure both width and right would represent bytes 8..11 of the memory block and height and bottom would represent bytes 12..15.

The purpose of a structure is to add human readable labels to a block of memory that represents multiple fixed datum of predetermined size and ordering, the memory block in this case is said to be structured memory and hence the name "structures"

Hope this helps

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

The UNION example apparently uses GoAsm syntax. Here is the same for MASM.

include \masm32\include\masm32rt.inc

RECT2 STRUCT
   top DWORD ?
   left DWORD ?
   UNION
       mywidth DWORD ?
       right DWORD ?
   ENDS
   UNION
       height DWORD ?
       bottom DWORD ?
   ENDS
RECT2 ENDS

.data?
rc RECT2 <?>

.code
start:

mov rc.mywidth, 123
mov rc.right, 456

MsgBox 0, str$(rc.right), "Hi", MB_OK
exit
end start

Astro

Hi,

Thanks! Making more sense now!

.data?
rc RECT2 <?>


Is this how you reference a structure? If I expect to receive a pointer to a structure from a function, how is that handled?

Best regards,
Astro.

jj2007

Quote from: Astro on July 24, 2009, 01:47:54 PM
Is this how you reference a structure? If I expect to receive a pointer to a structure from a function, how is that handled?

You can pass either a pointer or the structure itself. The latter makes sense only for small structures, since all members are pushed individually on the stack - see also this thread. Below a complete example. Normally you would use
  mov edx, MyPtr
  mov eax, [edx.RECT.top]


include \masm32\include\masm32rt.inc

.code
myrect RECT <123, 456, 111, 222>

TestMeP proc MyPtr
  mov edx, MyPtr
  print str$( [edx.RECT.top] ), " is the top of the rectangle", 13, 10
  ret
TestMeP endp

TestMeS proc MyStruc:RECT
  print str$(MyStruc.top), " is the top of the rectangle", 13, 10
  ret
TestMeS endp

start:
  invoke TestMeP, offset myrect
  invoke TestMeS, myrect
  exit

end start


Note I put the myrect   RECT <123, 456, 111, 222> into the .code section before start. This is legal but read-only.

Variants:
.data?
myrect2   RECT <?>  ; all members zero, does not increase exe size

.data
myrect3   RECT <1,2,3,4>

ecube

Quote from: Astro on July 24, 2009, 01:47:54 PM
Hi,

Thanks! Making more sense now!

.data?
rc RECT2 <?>


Is this how you reference a structure? If I expect to receive a pointer to a structure from a function, how is that handled?

Best regards,
Astro.

can do

.data?
rc RECT2 <?>

.code
start:
invoke myfunction,addr rc

myfunction proc lparm:DWORD
mov ecx,lparm
assume ecx:ptr RECT2

;do stuff here
mov edi,[ecx].down

;if it was a buffer use addr
invoke lstrcpy,addr mybuf,addr [ecx].buffer

;when finished
assume ecx:ptr NOTHING

ret
myfunction endp


;another way
myfunction proc lparm:DWORD
local myrec:RECT2

;copy the structured memory over
invoke RtlMoveMemory,addr myrec,lparm,sizeof myrec

;do stuff here
mov edi,myrec.down

;if it was a buffer use addr
invoke lstrcpy,addr mybuf,addr myrec.buffer

ret
myfunction endp


keep in mind when you use CreateThread which only takes 1 parameter, the best way to pass multiple values is using structures like above

Astro

OK - thanks!

Going to have to write a few examples I think before it fully sinks in.

Best regards,
Astro.

donkey

Quote from: jj2007 on July 24, 2009, 07:47:03 AM
The UNION example apparently uses GoAsm syntax. Here is the same for MASM.

Actually language neutral - ENDSTRUCT and ENDUNION were not intended to be specific to any language, simply easily readable.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Astro

If I'm being passed a pointer to a structure from an API, do I need to define the structure in my code even though it came from elsewhere?

Best regards,
Astro.

Slugsnack

if it's already defined in an include file that you have included then no you don't

dedndave

Astro,
  Most (if not all) structures that are used for API's are defined in "\masm32\include\windows.inc".
You can use the Find feature in the text editor to locate the structure in that file and see what elements it uses.
In many cases, the structure is comprised of other structures that are also defined in the same file.
  If you use "INCLUDE \masm32\include\masm32rt.inc" at the beginning of the program, that file contains
the include, "INCLUDE \masm32\include\windows.inc", so the structures are all predefined.
  For example, I use the CONSOLE_CURSOR_INFO structure in many programs. In the data area,
all you need is:

        .data?
CursInfo   CONSOLE_CURSOR_INFO <>

Now, you can access the elements in that structure individually:

        mov     eax,CursInfo.bVisible

Astro

Great. Thanks!  :thumbu

Best regards,
Astro.