Atualizado: 30/08/2025

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

Multiplicação de Inteiros em Assembly NASM: As Instruções mul e imul

A arquitetura x86-64 fornece duas instruções primárias para a multiplicação de inteiros, cuja escolha depende do contexto dos dados:

  • mul: Realiza a multiplicação de inteiros sem sinal (unsigned).
  • imul: Realiza a multiplicação de inteiros com sinal (signed), tratando os valores na representação em complemento de dois.

Ambas as instruções, em sua forma mais fundamental, operam de maneira implícita, utilizando o registrador RAX (ou suas partes menores EAX, AX, AL) como um dos fatores e o destino principal.

mul e imul: A Forma Clássica de Um Operando

A sintaxe mais básica e poderosa para ambas as instruções aceita um único operando, que pode ser um registrador ou um endereço de memória.

mul source ou imul source

O funcionamento desta forma é projetado para lidar com o fato de que a multiplicação de dois números de n bits pode gerar um resultado de até 2n bits.

  1. O valor em source (o operando explícito) é multiplicado por um operando implícito, que é RAX ou uma de suas subpartes (AL, AX, EAX), dependendo do tamanho de source.
  2. O resultado completo (2n bits) é armazenado em um par de registradores para evitar perda de dados.

A tabela a seguir detalha essa operação:

Tamanho de sourceOperando ImplícitoOperação RealizadaDestino (Parte Alta : Parte Baixa)
8 bits (byte)ALAL * sourceAH : AL (ou seja, AX)
16 bits (word)AXAX * sourceDX : AX
32 bits (dword)EAXEAX * sourceEDX : EAX
64 bits (qword)RAXRAX * sourceRDX : RAX

Se a parte alta do resultado (ex: RDX) for diferente de zero, significa que o resultado excedeu a capacidade do registrador da parte baixa (ex: RAX). Nesse caso, as instruções mul e imul ativam os flags de Carry (CF) e Overflow (OF) para sinalizar o estouro.

Exemplo 1: Resultado que Cabe na Parte Baixa (Linux)

global _start
section .text
_start:
    mov rax, 4      ; Operando implícito
    mov rdi, 2      ; Operando explícito (source)
    mul rdi         ; Executa RDX:RAX = RAX * RDI. Resultado: 4 * 2 = 8.
                    ; RDX fica com 0, RAX fica com 8. CF e OF são 0.
    mov rdi, rax    ; rdi = 8 (para o código de saída)
    mov rax, 60
    syscall

Exemplo 2: Resultado que Utiliza a Parte Alta (Linux)

global _start
section .text
_start:
    mov rax, 0xC000000000000002
    mov rdi, 4
    mul rdi           ; RDX:RAX = 0xC000000000000002 * 4
                      ; Resultado completo: 0x30000000000000008
                      ; RDX = 3 (parte alta)
                      ; RAX = 8 (parte baixa)
    mov rdi, rdx      ; Inspecionando a parte alta do resultado.
    mov rax, 60
    syscall

Esta forma de um operando é essencial quando a precisão máxima é necessária e a perda de dados por estouro não é uma opção.

As Formas Convenientes da Instrução imul

Diferentemente de mul, a instrução imul (para números com sinal) oferece sintaxes mais flexíveis e intuitivas com dois e três operandos, que se assemelham mais às operações em linguagens de alto nível.

Importante: Essas formas de imul são mais convenientes, mas têm uma limitação: a parte alta do resultado da multiplicação é descartada. Elas são úteis apenas quando você tem certeza de que o resultado caberá no registrador de destino.

1. imul com Dois Operandos

imul destination, source

Esta forma multiplica destination por source e armazena o resultado (apenas a parte baixa) em destination.

  • destination: Registrador.
  • source: Registrador, memória ou constante.
global _start
section .text
_start:
    mov rdi, 3
    imul rdi, 5     ; rdi = rdi * 5 => rdi = 15
    mov rax, 60
    syscall

2. imul com Três Operandos

imul destination, source, constant

Esta forma multiplica source pela constant e armazena o resultado (apenas a parte baixa) em destination.

  • destination: Registrador.
  • source: Registrador ou memória.
  • constant: Valor imediato.
global _start
section .text
_start:
    mov rdx, 3
    imul rdi, rdx, 4     ; rdi = rdx * 4 => rdi = 12
    mov rax, 60
    syscall

Resumo

  • mul é usada para multiplicação de inteiros sem sinal e existe apenas na forma de um operando.
  • imul é usada para multiplicação de inteiros com sinal e existe em três formas (um, dois e três operandos).
  • A forma de um operando é a única que preserva o resultado completo de 2n bits em um par de registradores (ex: RDX:RAX), sendo essencial para cálculos de alta precisão.
  • As formas de dois e três operandos de imul são mais convenientes e legíveis, mas descartam a parte alta do resultado, sendo seguras apenas quando não há risco de estouro.
  • Os flags CF e OF são ativados em todas as formas se o resultado da multiplicação exceder a capacidade do registrador de destino principal.
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