Structs and unions are special forms of scopes. They are to some degree comparable to their C counterparts. Both have a list of members. Each member allocates storage and may optionally have a name, which, in case of a struct, is the offset from the beginning and, in case of a union, is always zero.
Here is an example for a very simple struct with two members and a total size of 4 bytes:
.struct Point
xcoord .word
ycoord .word
.endstruct
A union shares the total space between all its members, its size is the same as that of the largest member.
A struct or union must not necessarily have a name. If it is anonymous, no local scope is opened, the identifiers used to name the members are placed into the current scope instead.
A struct may contain unnamed members and definitions of local structs. The storage allocators may contain a multiplier, as in the example below:
.struct Circle
.struct Point
.word 2 ; Allocate two words
.endstruct
Radius .word
.endstruct
Using the .TAG keyword, it is possible to embedd already defined structs or unions in structs:
.struct Point
xcoord .word
ycoord .word
.endstruct
.struct Circle
Origin .tag Point
Radius .byte
.endstruct
Space for a struct or union may be allocated using the .TAG directive.
C: .tag Circle
Currently, members are just offsets from the start of the struct or union. To access a field of a struct, the member offset has to be added to the address of the struct itself:
lda C+Circle::Radius ; Load circle radius into A
This may change in a future version of the assembler.