Atualizado: 18/10/2025

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

Chamada de Funções Assembly a partir de C/C++

Assim como o código em Assembly pode chamar funções escritas em C ou C++, também é possível fazer o inverso: chamar funções implementadas em Assembly a partir de um programa C/C++. Nesses casos, aplicam-se as mesmas convenções de passagem de parâmetros e retorno de resultados definidas pelo ABI da plataforma (System V ABI no Linux e Microsoft Windows ABI no Windows).


Linux

Considere o seguinte arquivo sum.asm, que define uma função simples para somar dois números:

global sum

section .text
; Função retorna a soma de dois números
; Recebe dois parâmetros:
; rdi - primeiro número
; rsi - segundo número
; Resultado retornado em rax
sum:
    mov rax, rdi
    add rax, rsi
    ret

A função recebe dois valores inteiros pelos registradores RDI e RSI e devolve o resultado em RAX. Para gerar o arquivo objeto:

nasm -f elf64 sum.asm -o sum.o

Agora, o programa principal em C — app.c — pode utilizar essa função:

#include <stdio.h>

int sum(int, int); // protótipo da função em Assembly

int main(void) {
    int result = sum(4, 2);    // chamada da função Assembly
    printf("result = %d\n", result);
}

O protótipo int sum(int, int) deve corresponder exatamente à assinatura da função em Assembly, garantindo compatibilidade de tipos e convenções de chamada.

Para compilar e vincular os arquivos:

gcc app.c sum.o -o app

Execução:

root@programicio:~/asm# nasm -f elf64 sum.asm -o sum.o
root@programicio:~/asm# gcc app.c sum.o -o app
root@programicio:~/asm# ./app
result = 6

Windows

A versão equivalente em Windows muda apenas os registradores usados para o envio dos parâmetros, seguindo o Microsoft Windows ABI. O código Assembly em sum.asm fica assim:

global sum

section .text
; Função retorna a soma de dois números
; Recebe dois parâmetros:
; rcx - primeiro número
; rdx - segundo número
; Resultado retornado em rax
sum:
    mov rax, rcx
    add rax, rdx
    ret

Os registradores RCX e RDX substituem RDI e RSI, conforme a convenção do Windows. Geração do arquivo objeto:

nasm -f win64 sum.asm -o sum.obj

O programa C permanece idêntico à versão do Linux:

#include <stdio.h>

int sum(int, int); // protótipo da função em Assembly

int main(void) {
    int result = sum(4, 2);    // chamada da função Assembly
    printf("result = %d\n", result);
}

A compilação depende do compilador utilizado:

Com GCC (MinGW):

gcc app.c sum.obj -o app.exe

Com Microsoft Visual C++ (cl.exe):

cl app.c sum.obj

Considerações Importantes

  1. A convenção de chamada deve ser idêntica nos dois lados — C/C++ e Assembly. Isso inclui a ordem dos parâmetros, registradores utilizados e tipo de retorno.
  2. As funções Assembly podem ser declaradas como extern em C, e os arquivos devem ser vinculados juntos na etapa de linkagem.
  3. Tanto no Linux quanto no Windows, o nome exportado pela diretiva global (como sum) precisa coincidir exatamente com o nome usado no protótipo C.
  4. Para projetos maiores, é recomendável declarar as funções Assembly em um cabeçalho separado (.h) para evitar inconsistências de protótipo.

Resumo

  • C e C++ podem chamar funções Assembly da mesma forma que Assembly pode chamar funções C/C++.
  • No Linux, parâmetros são passados por RDI, RSI, RDX, RCX, R8, R9 (System V ABI).
  • No Windows, os quatro primeiros parâmetros usam RCX, RDX, R8, R9 (Microsoft Windows ABI).
  • O resultado é retornado em RAX.
  • É essencial que o protótipo em C corresponda à assinatura definida em Assembly.
  • A compilação e linkagem unem os arquivos .c e .o (ou .obj) no executável final.
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