News:

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

About Alignment in structures

Started by Rainstorm, February 03, 2008, 03:41:36 AM

Previous topic - Next topic

Rainstorm

hi,

when stuff is aligned in STRUCTURES that affects offsets at which the individual elements reside in memory & the memory access is that right ?

so is there any soultion to this.. or anyway to go about doing this, like i mean if i were accessing the fields through some addressing mode (word ptr [edx+2] etc), cause there would be padded bytes in some places

t  y

u

MASM doesn't auto-align struct members, so there are no problems :)

You do the padding manually, like:



object struct
someByte db ?
padding1 db ? ; this
someWord1 dw ?
someWord2 dw ?
padding2 dw ? ; this
objectPtr dd ?
...
Please use a smaller graphic in your signature.

Vortex

Hi Rainstorm,

A classical example of alignment is the usage of binary resource templates. A structure defining a template must be DWORD aligned.

jj2007

Quote from: Ultrano on February 03, 2008, 05:05:53 AM
MASM doesn't auto-align struct members, so there are no problems :)
You do the padding manually, like:

Here is one example that works:

MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_B, 201> ; Bold
ACCEL <FCONTROL or FVIRTKEY, VK_I, 202> ; Italics
ACCEL <FCONTROL or FVIRTKEY, VK_F, 203> ; Find

However, that structure is defined as follows in windows.inc:

ACCEL STRUCT WORD
  fVirt BYTE ?
  key   WORD ?
  cmd   WORD ?
ACCEL ENDS


So MASM provides for padding and alignment... but I would not fully rely on it. Test it case by case.

MichaelW

MASM does not automatically align structure members as the C/C++ compilers do:

http://msdn2.microsoft.com/en-us/library/aa290049.aspx

With WORD alignment specified, the ACCEL structure is aligned as the compilers would align it, with the key and cmd members aligned on their natural boundary, and this is what the API functions expect. If the WORD alignment is not specified, the default alignment is BYTE so the second and third members end up misaligned by one byte, and this misalignment causes my test code to fail.
eschew obfuscation

ToutEnMasm


For structures alignment use ml /Zp4, it's a defaut alignment that solve many problems.

Rainstorm

hi.

Thanks everyone for the feedback,  links,  & examples.
That was very helpful
-

jj2007

Quote from: ToutEnMasm on February 03, 2008, 06:15:31 PM
For structures alignment use ml /Zp4, it's a defaut alignment that solve many problems.

How would /Zp4 behave if you had a structure with three words?

evlncrn8

it would pad the struct with an additional byte making the struct 4 bytes in size i would imagine...

MichaelW

The /Zp4 option works correctly, but only because "the fields are aligned to the minimum of the field's size and the alignment." Because of this /Zp8 would be a better choice because it will duplicate the action of the compilers for fields of 8 bytes, as well as fields of 1, 2, and 4 bytes.

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

    _ACCEL STRUCT
      fVirt DB ?
      key   DW ?
      cmd   DW ?
    _ACCEL ENDS

    _TEST STRUCT
      dummy DB ?
      quad  DQ ?
    _TEST ENDS

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      accel ACCEL <>
      align 4
      _accel _ACCEL <>
      align 8
      _test _TEST <>
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    print ustr$(OFFSET accel.fVirt),13,10
    print ustr$(OFFSET accel.key),13,10
    print ustr$(OFFSET accel.cmd),13,10,13,10

    print ustr$(OFFSET _accel.fVirt),13,10
    print ustr$(OFFSET _accel.key),13,10
    print ustr$(OFFSET _accel.cmd),13,10,13,10

    print ustr$(OFFSET _test.dummy),13,10
    print ustr$(OFFSET _test.quad),13,10,13,10

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


Result with no alignment option:

4206592
4206594
4206596

4206600
4206601
4206603

4206608
4206609


Result with /Zp8 option:

4206592
4206594
4206596

4206600
4206602
4206604

4206608
4206616


BTW, there is no /Zp8 option listed in the MASM 6.0 reference, but it obviously works with 6.14.

eschew obfuscation

jj2007

The original ACCEL structure works with all Zp settings (the minimum is Zp1). The modified _ACCEL fails with /Zp1 but works with /Zp8. The key for understanding this is indeed in the phrase you quoted:

"the fields are aligned to the minimum of the field's size and the alignment"

i.e. the fVirt DB ? gets
no padding byte with Zp1
one padding byte with Zp1
one padding byte with Zp8

Thanks for clarifying this, Michael. I was actually afraid that the whole 5-byte or 6-byte structure would get padded to 8 byte alignments, which is not the case.


;Testkey with original ACCEL, WORD
; MyAccels ACCEL <FCONTROL or FVIRTKEY, VK_B, 200>
; _ACCEL <FCONTROL or FVIRTKEY, VK_B, 201> ; Bold
; _ACCEL <FCONTROL or FVIRTKEY, VK_I, 202> ; Italics
; _ACCEL <FCONTROL or FVIRTKEY, VK_F, 203> ; Find
; _ACCEL <FCONTROL or FVIRTKEY, VK_S, 204> ; Save
; _ACCEL <FVIRTKEY, VK_F3, 205> ; Repeat find

; ....

push esi
push ebx

mov esi, offset MyAccels
mov ebx, offset ClBuffer
invoke lstrcpy, ebx, chr$("Test:")

invoke lstrcat, ebx, chr$(crlf,"A1=")
xor eax, eax
add ax, word ptr[esi+4]
invoke lstrcat, ebx, str$(eax)
add esi, 6

invoke lstrcat, ebx, chr$(crlf,"A2=")
xor eax, eax
add ax, word ptr[esi+4]
invoke lstrcat, ebx, str$(eax)
add esi, 6

invoke lstrcat, ebx, chr$(crlf,"A3=")
xor eax, eax
add ax, word ptr[esi+4]
invoke lstrcat, ebx, str$(eax)
add esi, 6

invoke lstrcat, ebx, chr$(crlf,"A4=")
xor eax, eax
add ax, word ptr[esi+4]
invoke lstrcat, ebx, str$(eax)

invoke MessageBox, 0, ebx, addr AppName, MB_OK

pop ebx
pop esi