Atualizado: 18/10/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Estruturas de Dados em Assembly NASM

O NASM, assim como o GNU Assembler, não possui suporte nativo a estruturas como tipo de dado, diferentemente de linguagens de mais alto nível. No entanto, é possível simular estruturas organizando manualmente os dados na memória de forma contígua.


Estrutura Simples em Memória

section .data
; estrutura simbólica
person:
    db "Alice", 10    ; nome
    dq 34             ; idade

Aqui, a variável person representa dois elementos consecutivos na memória: uma string e um número de 64 bits. Essa combinação pode ser entendida como uma estrutura que descreve uma pessoa — o nome e a idade.

Exemplo: Exibindo Nome e Idade

global _start

section .data
; estrutura simbólica
person:
    db "Alice", 10    ; nome
    dq 34             ; idade

; deslocamentos dos campos na estrutura
NAME_OFFSET equ 0
AGE_OFFSET equ 6

section .text
_start:
    mov rsi, person       ; RSI - endereço do nome
    mov rdi, 1            ; RDI - descritor de saída padrão (console)
    mov rdx, AGE_OFFSET   ; RDX - tamanho do nome em bytes
    mov rax, 1            ; RAX - syscall write
    syscall

    mov rdi, [rsi + AGE_OFFSET]  ; RDI - idade
    mov rax, 60
    syscall

Nesta estrutura, o campo NAME_OFFSET representa o deslocamento inicial (0 bytes), e AGE_OFFSET indica o deslocamento do campo de idade, que começa no 6º byte, após o nome “Alice”.

Durante a execução:

  • RSI aponta para o início da estrutura (a string).
  • RDX contém o tamanho da string (6 bytes, incluindo o caractere de nova linha).
  • A chamada syscall com RAX = 1 imprime o nome.
  • A idade é carregada a partir do endereço person + AGE_OFFSET.

Saída:

programicio@machine:~/asm$ nasm -f elf64 hello.asm -o hello.o
programicio@machine:~/asm$ ld hello.o -o hello
programicio@machine:~/asm$ ./hello
Alice
programicio@machine:~/asm$ echo $?
34

Estrutura com Endereços

Esse método simples tem limitações: se o nome tiver tamanho variável, o deslocamento de cada campo muda. Uma solução é armazenar endereços e tamanhos dentro da estrutura, em vez da string diretamente:

global _start

section .data
; estrutura simbólica
person:
    dq alice             ; endereço da string
    dq alice_name_size   ; tamanho da string
    dq 34                ; idade

; deslocamentos dos campos
NAME_OFFSET equ 0
NAME_SIZE_OFFSET equ 8
AGE_OFFSET equ 16

alice db "Alice", 10
alice_name_size equ $ - alice

section .text
_start:
    mov rbx, person
    mov rsi, [rbx + NAME_OFFSET]       ; RSI - endereço da string
    mov rdi, 1                         ; RDI - descritor de saída padrão
    mov rdx, [rbx + NAME_SIZE_OFFSET]  ; RDX - tamanho do nome
    mov rax, 1                         ; syscall write
    syscall

    mov rdi, [rbx + AGE_OFFSET]        ; RDI - idade
    mov rax, 60
    syscall

Agora, a estrutura person contém três campos de 8 bytes cada (.quad):

  1. Endereço da string.
  2. Tamanho da string.
  3. Idade.

Isso facilita o gerenciamento e o reuso de estruturas.

Campos e Deslocamentos

; estrutura simbólica
person:
    dq alice
    dq alice_name_size
    dq 34

; deslocamentos
NAME_OFFSET equ 0
NAME_SIZE_OFFSET equ 8
AGE_OFFSET equ 16

alice db "Alice", 10
alice_name_size equ $ - alice

Cada campo ocupa 8 bytes, portanto o tamanho total da estrutura é 24 bytes. Esse formato padronizado permite manipular coleções de estruturas sem recalcular tamanhos manualmente.

Exemplo: Array de Estruturas

O exemplo a seguir mostra como percorrer um array de estruturas contendo nome e idade de várias pessoas:

global _start

section .data
; array de estruturas
people:
    dq tom, tom_name_size, 39
    dq sam, sam_name_size, 29
    dq bob, bob_name_size, 43
    dq kate, kate_name_size, 25
    dq alice, alice_name_size, 34
count equ ($ - people) / PERSON_SIZE     ; número de elementos

tom db "Tom", 10
tom_name_size equ $ - tom
sam db "Sam", 10
sam_name_size equ $ - sam
bob db "Bob", 10
bob_name_size equ $ - bob
kate db "Kate", 10
kate_name_size equ $ - kate
alice db "Alice", 10
alice_name_size equ $ - alice

; deslocamentos e tamanho da estrutura
NAME_OFFSET equ 0
NAME_SIZE_OFFSET equ 8
AGE_OFFSET equ 16
PERSON_SIZE equ 24

section .text
_start:
    mov r9, 0          ; contador
    mov rbx, people
    jmp condition

mainloop:
    mov rbx, people
    mov rax, PERSON_SIZE
    mul r9
    add rbx, rax

    mov rsi, [rbx + NAME_OFFSET]       ; RSI - endereço do nome
    mov rdi, 1                         ; RDI - descritor de saída padrão
    mov rdx, [rbx + NAME_SIZE_OFFSET]  ; RDX - tamanho do nome
    mov rax, 1
    syscall

    inc r9
condition:
    cmp r9, count
    jne mainloop

    mov rdi, r9
    mov rax, 60
    syscall

Aqui, o registrador R9 atua como índice de iteração, movendo-se de uma estrutura para a seguinte conforme o tamanho fixo PERSON_SIZE.

Saída esperada:

Tom
Sam
Bob
Kate
Alice

Conclusão

  • O NASM não oferece estruturas nativas, mas é possível emular esse comportamento com dados sequenciais.
  • Os deslocamentos (OFFSET) permitem acessar campos individuais dentro da estrutura.
  • Usar endereços e tamanhos em vez de dados diretos torna o formato mais flexível e consistente.
  • Com tamanho fixo (PERSON_SIZE), é possível criar e percorrer arrays de estruturas com facilidade.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com