What is the purpose of an unnamed struct?
For example, in Window.inc is the following:
CY STRUCT
struct
Lo dd ?
Hi dd ?
ENDS
int64 dq ?
CY ENDS
and
What is the effect of putting DWORD after the struct .e.q. also in Windows.inc
IID STRUCT DWORD
Data1 dd ?
Data2 dw ?
Data3 dw ?
Data4 db 8 dup(?)
IID ENDS
Quote from: JimgWhat is the effect of putting DWORD after the struct .e.q. also in Windows.inc
Alignment. BYTE = 1, WORD = 2, DWORD = 4.
MASM Programmer's Guide, Chapter 5, Structures and Unions, Alignment Value and Offsets for Structures.
MASM Programmer's Guide (http://doc.ddart.net/asm/Microsoft_MASM_Programmers_Guide_v6.1/Chap_05.htm)
There is a brief description of the structure and union alignments that the compiler implements, which must generally be duplicated in structures and unions used with the API, here (see Structure and Union Layout):
http://msdn2.microsoft.com/en-us/library/aa290049(VS.71).aspx
Both examples are not very good, because CY indeed *is* a union, not a struct, which has a size of 8 bytes, and the DWORD alignment parameter for IID has no effect at all.
Thanks guys, I must have been really tired last night when I was trying to figure this out :red
japheth-
When I print out the SIZEOF CY, it prints out as 16. So it's not really a union, right?
After reading the alignment description at least 10 times, wouldn't an IID structure-
IID STRUCT DWORD
Data1 dd ?
Data2 dw ?
Data3 dw ?
Data4 db 8 dup(?)
IID ENDS
come out like:
offset
IID+0 Data1
+1 .
+2 .
+3 .
+4 Data2
+5 .
+6 (unused fill to align Data3)
+7 (unused fill)
+8 Data3
+9 .
+10 (unused fill to align Data4
+11 (unused fill)
+12 Data4
+13 .
+14 .
+15 .
+16 .
+17 .
+18 .
+19 .
but when I print SIZEOF IID, I get 16, which means no padding was applied ??
And back to my original question---
What is the purpose of an unnamed struct?
For example, in Window.inc is the following:
Code:
CY STRUCT
struct
Lo dd ?
Hi dd ?
ENDS
int64 dq ?
CY ENDS
wouldn't this be exactly equal to:
CY STRUCT
Lo dd ?
Hi dd ?
int64 dq ?
CY ENDS
???
The only difference I can see between the version with the unnamed structure and the version without is that the unnamed structure must be initialized as a single item. At the moment I can't think of any good reason to use such an unnamed structure.
If IID were defined as a union (in which case it would need to be renamed to avoid a conflict) SIZEOF would return the size of the largest field.
Because the fields are aligned to the minimum of the alignment and the field size, alignment has no effect on structures where the fields are ordered from largest to smallest.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
SCY STRUCT
STRUCT
Lo dd ?
Hi dd ?
ENDS
int64 dq ?
SCY ENDS
_SCY STRUCT
Lo dd ?
Hi dd ?
int64 dq ?
_SCY ENDS
UIID UNION
Data1 dd ?
Data2 dw ?
Data3 dw ?
Data4 db 8 dup(?)
UIID ENDS
SIID STRUCT 4
Data1 dd ?
Data2 dw ?
Data3 dw ?
Data4 db 8 dup(?)
SIID ENDS
S1 STRUCT
f1 BYTE ?
f2 WORD ?
f3 BYTE ?
f4 DWORD ?
S1 ENDS
S2 STRUCT 2
f1 BYTE ?
f2 WORD ?
f3 BYTE ?
f4 DWORD ?
S2 ENDS
S4 STRUCT 4
f1 BYTE ?
f2 WORD ?
f3 BYTE ?
f4 DWORD ?
S4 ENDS
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
scy SCY <{11111111h,22222222h},3333333333333333h>
_scy _SCY <11111111h,22222222h,3333333333333333h>
uiid UIID <>
siid SIID <11111111h,2222h,3333h,{4,4,4,4,4,4,4,4}>
s1 S1 <11h,2222h,33h,44444444h>
s2 S2 <11h,2222h,33h,44444444h>
s4 S4 <11h,2222h,33h,44444444h>
buffer db 120 dup(0)
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
print ustr$(SIZEOF scy),13,10
print ustr$(SIZEOF _scy),13,10,13,10
invoke HexDump,ADDR scy,SIZEOF scy,ADDR buffer
print ADDR buffer
invoke HexDump,ADDR _scy,SIZEOF _scy,ADDR buffer
print ADDR buffer,13,10
print ustr$(SIZEOF uiid),13,10
print ustr$(SIZEOF siid),13,10,13,10
invoke HexDump,ADDR siid,SIZEOF siid,ADDR buffer
print ADDR buffer,13,10
print ustr$(SIZEOF s1),13,10
print ustr$(SIZEOF s2),13,10
print ustr$(SIZEOF s4),13,10,13,10
invoke HexDump,ADDR s1,SIZEOF s1,ADDR buffer
print ADDR buffer,13,10
invoke HexDump,ADDR s2,SIZEOF s2,ADDR buffer
print ADDR buffer,13,10
invoke HexDump,ADDR s4,SIZEOF s4,ADDR buffer
print ADDR buffer,13,10,13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Ignore the trailing zero on the partial dumps, I think this problem has already been reported and fixed in the next version of the HexDump procedure.
16
16
11 11 11 11 22 22 22 22 - 33 33 33 33 33 33 33 33
11 11 11 11 22 22 22 22 - 33 33 33 33 33 33 33 33
8
16
11 11 11 11 22 22 33 33 - 04 04 04 04 04 04 04 04
8
10
12
11 22 22 33 44 44 44 44 - 0
11 00 22 22 33 00 44 44 - 44 44 0
11 00 22 22 33 00 00 00 - 44 44 44 44 0
According to the document Greg pointed me to:
QuoteIf the field size in bytes is greater than the alignment value, the field is padded so that its offset is evenly divisible by the alignment value. Otherwise, the field is padded so that its offset is evenly divisible by the field size.
Any padding required to reach the correct offset for the field is added prior to allocating the field. The padding consists of zeros and always precedes the aligned field. The size of the structure must also be evenly divisible by the structure alignment value, so zeros may be added at the end of the structure.
I can't find anything that says:
QuoteBecause the fields are aligned to the minimum of the alignment and the field size, alignment has no effect on structures where the fields are ordered from largest to smallest.
Where did you find this?
the correct translation (from the PSDK .h file) is:
CY union
struct
Lo dd ?
Hi dd ?
ends
int64 dq ?
CY ends
and the reason is that CY is actually an union
mov eax,cy1.Lo
mov eax,cy1.Hi
fild cy1.int64
QuoteWhat is the purpose of an unnamed struct?
in this example CY represents both struct and a single value
Sure, it makes perfect sense if CY is a union.
So Windows.inc is in error and needs to be fixed, right?
Quote from: Jimg on April 20, 2007, 06:44:57 PMSo Windows.inc is in error and needs to be fixed, right?
right
Ok, so far we have:
I screwed up and pick an example (CY) that had other problems thus obscuring my original question about unnamed structs.
An unnamed struct has no reason to exist and to avoid superfluous confusion we shouldn't use it
Masm does not assign storage for structs with the alignment parameter correctly, or at least not how it says it does.
As drizz says, an unnamed struc is useful in a union.
so, otherwise there is no reason to use it. Or perhaps, you could insert several unnamed structures and reference them using array notation?
Alright, after reading it for at least the 30th time, I finally SEE what it says. My sincerest apologies for my ignorance. I even underlined the important part, and still didn't get it. Otherwise, the field is padded so that its offset is evenly divisible by the field size.
The last words are FIELD SIZE, not alignment size, i.e. the size of the field being defined. Ugh. Some days it's not worth getting out of bed.
so, clarifying the description somewhat for myself-
If the size in bytes of the field being defined is greater than the alignment value, then enough zero bytes are inserted before the field so that its offset is evenly divisible by the alignment value.
Likewise, if the size in bytes of the field being defined is less than or equal to the alignment value, then enough zero bytes are inserted before the field so that its offset is evenly divisible by the size of the field being defined.
Just like Michael said: "... the fields are aligned to the minimum of the alignment and the field size ..."
FWIW at this point, here is the original definition of CY from WinNT.h, complete with comments:
/* the following isn't the real definition of CY, but it is */
/* what RPC knows how to remote */
typedef struct tagCY
{
LONGLONG int64;
} CY;
#else /* 0 */
/* real definition that makes the C++ compiler happy */
typedef union tagCY {
struct {
#ifdef _MAC
long Hi;
long Lo;
#else
unsigned long Lo;
long Hi;
#endif
};
LONGLONG int64;
} CY;
So it looks to me like the MASM definition should be a structure within a union, just as drizz defined it, and using an unnamed structure seems entirely reasonable, given that Microsoft did the same in at least one of the examples in the MASM Programmer's Guide:
uptr UNION
dwptr FPWORD 0
STRUCT
offs WORD 0
segm WORD 0
ENDS
uptr ENDS
Just a quick look at what I can find on the net from Microsoft I get this structure in C (I removed the #ifdef for the MAC) which converts to MASM something like as follows.
typedef union FARSTRUCT tagCY {
struct {
unsigned long Lo;
long Hi;
};
LONGLONG int64;
} CY;
CY UNION
STRUCT
Lo DWORD ?
Hi DWORD ?
ENDS
int64 QWORD ?
CY ENDS
Hi Hutch
Sorry to come again with this issue but the WinExtra.inc contains the following definition
CY STRUCT
struct
Lo dd ?
Hi dd ?
ENDS
int64 dq ?
CY ENDS
Pleace take note for the next release.
Regards,
Biterider
Biterider,
Thanks, I already have it in this form in the reference set. I just have not released another version yet.
CY UNION
STRUCT
Lo DWORD ?
Hi DWORD ?
ENDS
int64 QWORD ?
CY ENDS