Atualizado: 09/11/2025

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

Aritmética com Números de Ponto Flutuante em Assembly NASM

As extensões SSE fornecem um conjunto de instruções para realizar operações aritméticas sobre números de ponto flutuante. Essas instruções operam sobre valores armazenados nos registradores XMM e podem manipular tanto números de precisão simples (32 bits) quanto de precisão dupla (64 bits).

Principais instruções

InstruçãoOperação
addss, addsdAdição
subss, subsdSubtração
mulss, mulsdMultiplicação
divss, divsdDivisão
minss, minsdRetorna o menor valor entre dois operandos
maxss, maxsdRetorna o maior valor entre dois operandos
sqrtss, sqrtsdCalcula a raiz quadrada
rcpss, rcpsdCalcula o inverso (1/x)
rsqrtss, rsqrtsdCalcula o inverso da raiz quadrada (1/√x)

Os sufixos indicam o tipo de dado manipulado:

  • ss (scalar single) — operações sobre valores de ponto flutuante de 32 bits.
  • sd (scalar double) — operações sobre valores de ponto flutuante de 64 bits.

Formato geral das instruções

addss xmm, xmm/mem32
addsd xmm, xmm/mem64

subss xmm, xmm/mem32
subsd xmm, xmm/mem64

mulss xmm, xmm/mem32
mulsd xmm, xmm/mem64

divss xmm, xmm/mem32
divsd xmm, xmm/mem64

minss xmm, xmm/mem32
minsd xmm, xmm/mem64

maxss xmm, xmm/mem32
maxsd xmm, xmm/mem64

sqrtss xmm, xmm/mem32
sqrtsd xmm, xmm/mem64

rcpss xmm, xmm/mem32
rsqrtss xmm, xmm/mem32

O primeiro operando (onde o resultado é armazenado) deve ser sempre um registrador XMM. O segundo operando pode ser outro registrador XMM ou um operando de memória.


Exemplo: soma de dois números em Linux

global _start

section .data
num0 dq 3.4
num1 dq 6.6

section .text
_start:
    movsd xmm0, [num0]     ; carrega num0 em xmm0
    movsd xmm1, [num1]     ; carrega num1 em xmm1
    addsd xmm0, xmm1       ; xmm0 = xmm0 + xmm1
    cvtsd2si rdi, xmm0     ; converte resultado para inteiro em RDI

    mov rax, 60
    syscall

Neste exemplo, os números 3.4 e 6.6 são carregados em xmm0 e xmm1. Após a operação de soma, o resultado (10.0) é convertido para inteiro e armazenado em rdi.


Exemplo equivalente em Windows

global _start

section .data
num0 dq 3.4
num1 dq 6.6

section .text
_start:
    movsd xmm0, [rel num0]
    movsd xmm1, [rel num1]
    addsd xmm0, xmm1
    cvtsd2si rax, xmm0
    ret

A lógica é idêntica, com a diferença de endereçamento relativo ([rel var]) utilizado no ambiente Windows.


Outras operações

  • Subtração: subsd xmm0, xmm1 - calcula xmm0 = xmm0 - xmm1.
  • Multiplicação: mulsd xmm0, xmm1 - calcula xmm0 = xmm0 * xmm1.
  • Divisão: divsd xmm0, xmm1 - calcula xmm0 = xmm0 / xmm1.
  • Raiz quadrada: sqrtsd xmm0, xmm1 - calcula xmm0 = √xmm1.
  • Mínimo e máximo: minsd xmm0, xmm1 / maxsd xmm0, xmm1.
  • Inverso: rcpss xmm0, xmm1 - resultado ≈ 1 / xmm1.
  • Inverso da raiz quadrada: rsqrtss xmm0, xmm1 - resultado ≈ 1 / √xmm1.

Essas instruções também possuem variantes vetoriais (vaddsd, vsubsd, etc.) nas extensões AVX, que funcionam de maneira equivalente, mas com registradores YMM de 256 bits.


Resumo

  • As operações aritméticas com ponto flutuante são realizadas diretamente nos registradores XMM.
  • O sufixo ss indica operações com precisão simples (32 bits), e sd indica precisão dupla (64 bits).
  • O resultado das operações sempre é gravado no primeiro operando.
  • As instruções SSE/AVX permitem manipular tanto números escalares quanto vetores.
  • Conversões para inteiro podem ser feitas com instruções cvt*.
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