Me, Leandro, as a handdraw logo

A Diretiva Struc no NASM

Aug 15 · 3min

Recentemente, eu comecei a estudar NASM através desta série de tutoriais — e tantos outros… assim, como quem não quer nada. Entretanto, acabei por me interessar de maneira profunda e sistemática.

Eventualmente, me deparei com uma necessidade organizacional semelhante às estruturas em C, os structs. Em minhas pesquisas em documentações e outros repositórios, encontrei o uso da diretiva struc.

Definição

Assim como em qualquer outro lugar, devemos explicitar os seus campos para usos posteriores:

; Definição de estrutura
struc EstruturaExemplo
    .campo1 resd 1  ; reserva 4 bytes - 32 bits
    .campo2 resw 1  ; reserva 2 bytes - 16 bits
    .campo3 resb 1  ; reserva 1 byte  - 8 bits
endstruc

Note

Nota-se que struc é usado sem a letra 't'.

Como leitor astuto, você já identificou que cada campo possui o rótulo prefixado com um ponto, seguido pelo tamanho em bytes.

Os tamanhos são especificados usando as diretivas de reserva de dados do NASM: resb, resw, resd e resq.

DiretivaNomeTamanho por unidadeExemplo de uso
resbreserve byte1 byteresb 1 → 1 byte
reswreserve word2 bytesresw 1 → 2 bytes
resdreserve doubleword4 bytesresd 1 → 4 bytes
resqreserve quadword8 bytesresq 1 → 8 bytes

Tip

Você pode reservar múltiplas unidades. Por exemplo, resb 4 reserva 4 bytes no total.

Em geral, o total reservado é igual a diretiva × número (por exemplo, resw 3 reserva bytes).

Instanciando

Depois de definir a estrutura, precisamos criar instâncias usando as diretivas istruc e iend na section .data:

labels                   instruction   operands
---------------------------------------------------------------
                         section       .data

player_transform:        istruc        Transform
                         at            .x, dd  1.0
                         at            .y, dd  2.0
                         at            .z, dd  3.0
                         iend

Neste exemplo simplório, estamos criando uma instância de Transform e atribuindo o rótulo player_transform.

Note

A diretiva at serve para especificar qual campo da estrutura está sendo inicializado.

Acessando os campos

Acessar ou modificar os campos é bem tranquilo. Basta usar o nome/rótulo da estrutura e o deslocamento do campo:

label                    instruction     operand
---------------------------------------------------------------
                         section         .text
                         global          _start

_start:                  ; Carregar valor de X do player_transform em EAX
                         mov             eax, [player_transform + Transform.x]

                         ; Carregar valor de Y em EBX
                         mov             ebx, [player_transform + Transform.y]

                         ; Alterar valor de Z para 10.0
                         mov             dword [player_transform + Transform.z], __float32__(10.0)

                         ; ...
>
CC BY-NC-SA 4.0 2020–2025 © Leandro Peres. All rights reversed.