Structures in Assembly
A structure in assembly is a fixed layout of named byte offsets within a contiguous block of memory, grouping fields of possibly different sizes under one label the way a C struct does, except the assembler has no built-in concept of 'struct' — the programmer (or the assembler's macro facility) defines the offsets by hand. NASM's struc/endstruc directives let you declare field names that expand to constant offsets, so mov eax, [rsi + Point.y] reads a field by name instead of a hardcoded magic number, which is purely a readability aid; the generated machine code is identical to using the raw offset.
Cricket analogy: A player's scorecard entry with fixed columns for runs, balls faced, and fours, always in the same column order for every player, mirrors a structure's fixed field layout at constant offsets.
Declaring Structures with struc
The struc directive computes each field's offset automatically based on the cumulative size of the fields declared before it, so reordering fields changes every subsequent offset — this is why struct layout changes are binary-incompatible across separately assembled modules unless everything is rebuilt together. Padding and alignment are not automatic either; if a struct mixes byte and quadword fields, the programmer (or an alignment-aware macro) must insert explicit padding to keep multi-byte fields on aligned addresses, since misaligned accesses on x86-64 are legal but slower, and mandatory on some architectures.
Cricket analogy: Reordering a batting lineup mid-series changes every subsequent batting position by one slot, exactly like reordering struct fields shifts every following field's offset.
struc Point
.x: resd 1 ; offset 0, 4 bytes
.y: resd 1 ; offset 4, 4 bytes
endstruc
struc Player
.pos: resb Point_size ; offset 0, embedded Point (8 bytes)
.health: resd 1 ; offset 8
.name: resb 16 ; offset 12, fixed 16-byte buffer
endstruc
section .data
p1: istruc Player
at Player.pos + Point.x, dd 100
at Player.pos + Point.y, dd 200
at Player.health, dd 100
iend
section .text
global _start
_start:
mov eax, [p1 + Player.pos + Point.x] ; eax = 100
mov ebx, [p1 + Player.health] ; ebx = 100
mov eax, 60
xor edi, edi
syscall
Field names generated by struc (like Player.health) are just assembler-time constants equal to a byte offset — Player.health assembles to the literal number 8 wherever it's used. This means [rsi + Player.health] and [rsi + 8] produce byte-identical machine code; the name only helps the human reader and protects against typos if the layout changes.
Arrays of Structures and Nested Access
An array of structures is addressed the same way as an array of primitives, except the 'element size' is the struct's total size (available as StructName_size after struc/endstruc), so element i starts at base + i*StructName_size, and a field within that element is reached by adding the field's own offset on top: base + i*StructName_size + StructName.field. Nested structures (a struct containing another struct as a field, as with Player.pos above) simply chain offsets further — the total offset is the sum of every level's offset, computed once at assembly time and baked into the instruction as a single constant displacement.
Cricket analogy: Finding player 5's strike rate on a scorecard that lists five stats per player requires multiplying player number by five stats and adding the strike-rate column offset, exactly like base + i*size + field.
Nothing prevents assembling code against a stale or mismatched struct definition — if one module was assembled with an old Player layout (say, before a field was added) and linked against object code compiled with the new layout, every field access computes a wrong-but-plausible offset. This produces subtly corrupted data rather than a link error, since the linker has no type information to catch the mismatch.
- A structure is a fixed layout of named byte offsets in contiguous memory; the assembler has no native struct concept beyond what struc/endstruc generate.
- NASM's struc/endstruc directive computes field offsets automatically in declaration order, exposed as constants like Player.health.
- Field name constants (e.g. Player.health) are pure assembly-time numbers; using them versus a raw offset produces identical machine code.
- Reordering fields recalculates every subsequent field's offset, making struct layout changes binary-incompatible across separately assembled modules.
- Padding and alignment are manual; multi-byte fields inside mixed-size structs need explicit padding to stay aligned, since misalignment is legal on x86-64 but slower.
- An array of structs is indexed as base + i*StructName_size, with a specific field reached by adding that field's own offset on top.
- Mismatched struct layouts between separately assembled modules produce silently corrupted data, since the linker has no type information to detect the mismatch.
Practice what you learned
1. What does NASM's struc/endstruc directive actually generate?
2. Why does reordering fields in a struc definition matter for binary compatibility?
3. How is element i's field accessed in an array of structures?
4. What handles padding and alignment inside a struc-defined structure?
5. What happens if two separately assembled modules disagree on a struct's field layout?
Was this page helpful?
You May Also Like
Arrays in Assembly
How fixed-size, contiguous arrays are declared, laid out in memory, and indexed using scaled addressing in x86-64 assembly.
Pointers and Indirection
How addresses, dereferencing, pointer arithmetic, LEA, and multiple levels of indirection work at the machine level in x86-64 assembly.
The Heap and Dynamic Memory
How assembly programs request and manage runtime memory using brk/sbrk and mmap, and the manual bookkeeping needed to avoid leaks.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics