Atualizado: 18/10/2025

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

Definição e Chamada de Funções em Assembly NASM

As funções em Assembly permitem dividir um programa em partes menores chamadas sub-rotinas, cada uma responsável por executar um conjunto específico de instruções.

Na prática, uma função é um bloco de instruções associado a um rótulo, que serve como o nome da função. Toda função deve terminar com a instrução ret, responsável por devolver o controle para o ponto do código onde a função foi chamada.

Exemplo:

sum:
    mov rdi, 7
    mov rsi, 5
    add rdi, rsi
    ret

Neste caso, a função tem o nome sum. Ela apenas soma os valores armazenados nos registradores rdi e rsi, e o resultado fica em rdi.

A chamada de uma função é feita com a instrução call, seguida pelo nome da função:

call nome_da_funcao

A instrução call empilha no stack (pilha) o endereço de retorno — isto é, o endereço da próxima instrução após a chamada. Quando a função termina, a instrução ret recupera esse endereço do topo da pilha e transfere o controle de volta ao código que chamou a função.


Exemplo de Função em Linux:

global _start

section .text
_start:
    call sum      ; chama a função sum

    mov rax, 60   ; syscall para encerrar o programa
    syscall

; definição da função sum
sum:
    mov rdi, 7
    mov rsi, 5
    add rdi, rsi
    ret

Exemplo de Função em Windows:

global _start

section .text
_start:
    call sum      ; chama a função sum
    ret

; definição da função sum
sum:
    mov rax, 7
    mov rsi, 5
    add rax, rsi
    ret

Funções Chamando Outras Funções

Uma função pode chamar outras funções.

global _start

section .text
_start:
    call sum

    mov rax, 60
    syscall

sum:
    call set_rdi  ; chama a função set_rdi
    mov rsi, 5
    add rdi, rsi
    ret

set_rdi:
    mov rdi, 3
    ret

Aqui, a função sum chama a função set_rdi, que define rdi com o valor 3 antes de a soma ocorrer.

A Pilha e as Funções

Ao chamar uma função, a instrução call empilha o endereço de retorno. No final, ret deve encontrar esse endereço no topo da pilha. Se a pilha for manipulada incorretamente, o programa pode apresentar comportamento indefinido ou falhar.

Veja um exemplo incorreto:

global _start

section .text
_start:
    mov rdi, 3
    mov rsi, 9
    call sum

    mov rax, 60
    syscall

sum:
    push rsi       ; salva RSI na pilha
    add rdi, rsi
    ret

O problema é que o valor empilhado não foi removido antes da instrução ret. Assim, o endereço de retorno não estará mais no topo da pilha, resultando em erro de execução (como “Segmentation fault” no Linux).

Outro erro comum é retirar o endereço de retorno da pilha antes da instrução ret:

global _start

section .text
_start:
    mov rdi, 3
    mov rsi, 9
    call sum

    mov rax, 60
    syscall

sum:
    pop rsi        ; remove o endereço de retorno da pilha
    add rdi, rsi
    ret

Aqui, o endereço de retorno foi acidentalmente retirado com pop rsi. Assim, ret tentará retornar para um endereço inválido, resultando novamente em falha.

Portanto, uma função deve restaurar a pilha exatamente ao estado anterior à chamada, removendo apenas o que foi empilhado dentro dela.

Uso Direto do Endereço de Retorno

Também é possível acessar diretamente o endereço de retorno armazenado na pilha.

global _start

section .text
_start:
    mov rdi, 5
    mov rsi, 20
    call sum

    add rdi, 10    ; RDI = 15
    mov rax, 60
    syscall

sum:
    jmp [rsp]      ; salta para o endereço armazenado no topo da pilha
    add rdi, rsi   ; esta linha não será executada
    ret

A instrução jmp [rsp] faz um salto para o endereço que está no topo da pilha, que corresponde ao ponto imediatamente após a chamada de sum (ou seja, a instrução add rdi, 10).


Resumo

  • Uma função é um bloco de instruções identificado por um rótulo.
  • A instrução call chama a função e empilha o endereço de retorno.
  • A instrução ret restaura o controle ao código que chamou a função.
  • Alterar indevidamente o conteúdo da pilha pode causar falhas.
  • O endereço de retorno pode ser acessado diretamente, mas isso exige cuidado.
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