Resultado de Função em Assembly NASM
Em Assembly, as funções muitas vezes executam cálculos e produzem um resultado que precisa ser devolvido ao código principal.
Diferentemente das linguagens de alto nível, o Assembly não possui um operador como return.
Em arquiteturas x86-64, o resultado de uma função é normalmente armazenado em registradores, sendo o RAX o mais utilizado.
De acordo com as convenções de chamada System V ABI (Linux) e Microsoft Windows ABI, o valor de retorno de uma função é colocado em RAX. Isso é seguido também por linguagens como C e C++, o que facilita a interoperabilidade entre Assembly e código em alto nível.
Se o resultado for maior que 64 bits (por exemplo, 128 ou 256 bits), pode-se dividir o valor em partes e retornar cada parte em registradores diferentes, como RDX:RAX.
Para resultados ainda maiores, como grandes estruturas ou arrays, a função pode retornar o endereço da área de memória onde o valor foi armazenado.
Retornando um Valor Simples
Exemplo em Linux:
global _start
section .text
_start:
; define os parâmetros para a função sum
mov rdi, 5
mov rsi, 6
call sum ; após a chamada, RAX contém o resultado da soma
mov rdi, rax ; copia o resultado para RDI
mov rax, 60
syscall
; função sum realiza a soma de dois números
; RDI - primeiro número
; RSI - segundo número
; RAX - resultado da soma
sum:
mov rax, rdi
add rax, rsi
retA função sum recebe dois números pelos registradores rdi e rsi, realiza a soma e armazena o resultado em rax.
Após a chamada, o código principal pode usar o valor contido em rax.
Exemplo equivalente em Windows:
global _start
section .text
_start:
; define os parâmetros para a função sum
mov rcx, 5
mov rdx, 6
call sum ; após a chamada, RAX contém o resultado da soma
ret
; função sum realiza a soma de dois números
; RCX - primeiro número
; RDX - segundo número
; RAX - resultado da soma
sum:
mov rax, rcx
add rax, rdx
retRetornando a Soma dos Elementos de um Array
Exemplo em Linux:
global _start
section .data
nums dq 10, 20, 30, 15, 15
count equ ($ - nums) / numSize ; quantidade de elementos
numSize equ 8 ; tamanho de cada elemento
section .text
_start:
mov rdi, nums ; endereço do array
mov rsi, count ; quantidade de elementos
call sum ; após a chamada, RAX contém a soma total
mov rdi, rax
mov rax, 60
syscall
; função sum soma os elementos de um array
; RDI - endereço do array
; RSI - quantidade de elementos
; RAX - resultado da soma
sum:
xor rax, rax ; zera RAX para armazenar o resultado
jmp while_condition
while_begin:
dec rsi ; reduz o contador de elementos
add rax, [rdi + rsi * numSize] ; soma o elemento atual
while_condition:
cmp rsi, 0
jne while_begin
retA função sum percorre os elementos do array usando o endereço em rdi e o contador em rsi.
Cada valor é somado em rax, que guarda o resultado final ao término do loop.
Exemplo equivalente em Windows:
global _start
section .data
nums dq 10, 20, 30, 15, 15
count equ ($ - nums) / numSize
numSize equ 8
section .text
_start:
mov rcx, nums ; endereço do array
mov rdx, count ; quantidade de elementos
call sum ; após a chamada, RAX contém a soma total
ret
; função sum soma os elementos de um array
; RCX - endereço do array
; RDX - quantidade de elementos
; RAX - resultado da soma
sum:
xor rax, rax
jmp while_condition
while_begin:
dec rdx
add rax, [rcx + rdx * numSize]
while_condition:
cmp rdx, 0
jne while_begin
retResultados Maiores que 64 Bits
Quando o resultado ocupa mais de 64 bits, é possível dividir o valor em múltiplos registradores.
Por exemplo, um número de 128 bits pode ser retornado em RDX:RAX, onde RDX contém a parte mais significativa e RAX a menos significativa.
Para resultados muito grandes — como arrays extensos ou estruturas — o retorno deve ser feito por referência, ou seja, a função devolve o endereço de memória onde o resultado foi armazenado.
Resumo
- O resultado de uma função geralmente é colocado no registrador
RAX. - Funções podem usar outros registradores, mas
RAXé o padrão das convenções System V ABI e Windows ABI. - Resultados maiores que 64 bits podem ser divididos em múltiplos registradores (por exemplo,
RDX:RAX). - Para grandes estruturas ou arrays, retorna-se o endereço do resultado, não o valor em si.
- Após a chamada da função, o código principal acessa o resultado diretamente em
RAX.