Struc Directive in NASM

What is the struc Directive?

The struc directive in NASM is used to define a template for a structured data type. It specifies the layout of data in memory, similar to how struct in C/C++ works. This directive helps in organizing related data fields into a cohesive structure, making it easier to manage and access complex data.

Defining a Structure with struc

To define a structure in NASM, you use the struc and endstruc directives. Inside these directives, you specify the fields of the structure along with their sizes. Here's the syntax:

struc StructureName
    .field1 resd 1  ; Reserve 4 bytes for field1
    .field2 resw 1  ; Reserve 2 bytes for field2
    .field3 resb 1  ; Reserve 1 byte for field3
endstruc

Each field is defined with a label (prefixed by a dot) and a size. The sizes are specified using NASM's data reservation directives like resb (reserve byte), resw (reserve word), resd (reserve doubleword), and resq (reserve quadword).

  • struc StructureName: Begins the definition of a structure named StructureName.
  • .fieldX: Defines a field within the structure. The resb, resw, resd, and resq directives are used to reserve bytes, words, doublewords, and quadwords, respectively.
  • endstruc: Ends the structure definition.

istruc Employee
    at Employee.id, dd 2
    at Employee.name, db 'Jane Smith', 0
    at Employee.age, db 28
iend

Example: Defining an Employee Structure

Let's define a structure for an employee record:

struc Employee
    .id resd 1       ; 4 bytes for employee ID
    .name resb 32    ; 32 bytes for employee name
    .age resb 1      ; 1 byte for employee age
endstruc

This structure includes an employee ID, a name, and an age. The .id field is a doubleword (4 bytes), the .name field is a byte array (32 bytes), and the .age field is a single byte.

Instantiating and Initializing Structures

Once you've defined a structure, you can create instances of it using the istruc and iend directives. Here’s how you can instantiate and initialize an Employee structure:

section .data

employee1:
istruc Employee
    at Employee.id, dd 1                ; Initialize ID to 1
    at Employee.name, db 'John Doe', 0  ; Initialize name to 'John Doe'
    at Employee.age, db 30              ; Initialize age to 30
iend

In this example, we create an instance of Employee named employee1 and initialize its fields with specific values. The at directive is used to specify the field within the structure being initialized.

Accessing Structure Fields

Accessing and modifying the fields of a structure is straightforward. You use the structure's label and the field's offset:

section .text
global _start
_start:
    ; Load the employee ID into EAX
    mov eax, [employee1 + Employee.id]
    
    ; Increment the employee's age
    inc byte [employee1 + Employee.age]
    
    ; Program code continues...

In this code snippet, we load the employee ID into the EAX register and increment the employee's age directly in memory.