The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Rainstorm on February 03, 2008, 03:41:36 AM

Title: About Alignment in structures
Post by: Rainstorm on February 03, 2008, 03:41:36 AM
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
Title: Re: About Alignment in structures
Post by: u 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:



object struct
someByte db ?
padding1 db ? ; this
someWord1 dw ?
someWord2 dw ?
padding2 dw ? ; this
objectPtr dd ?
...
Title: Re: About Alignment in structures
Post by: Vortex on February 03, 2008, 09:10:34 AM
Hi Rainstorm,

A classical example of alignment is the usage of binary resource templates. A structure defining a template must be DWORD aligned.
Title: Re: About Alignment in structures
Post by: jj2007 on February 03, 2008, 01:34:20 PM
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.
Title: Re: About Alignment in structures
Post by: MichaelW on February 03, 2008, 03:02:55 PM
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.
Title: Re: About Alignment in structures
Post by: ToutEnMasm on February 03, 2008, 06:15:31 PM

For structures alignment use ml /Zp4, it's a defaut alignment that solve many problems.
Title: Re: About Alignment in structures
Post by: Rainstorm on February 03, 2008, 11:27:35 PM
hi.

Thanks everyone for the feedback,  links,  & examples.
That was very helpful
-
Title: Re: About Alignment in structures
Post by: jj2007 on February 04, 2008, 09:04:30 AM
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?
Title: Re: About Alignment in structures
Post by: evlncrn8 on February 04, 2008, 10:43:19 AM
it would pad the struct with an additional byte making the struct 4 bytes in size i would imagine...
Title: Re: About Alignment in structures
Post by: MichaelW on February 04, 2008, 11:21:58 AM
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.

Title: Re: About Alignment in structures
Post by: jj2007 on February 04, 2008, 12:15:24 PM
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