Multiplication and Division (mul, imul, div, idiv)

From MediaWiki
Jump to navigation Jump to search

Multiplication and Division (mul, imul, div, idiv)

This page explains how integer multiplication and division work in x86-64 assembly. It covers unsigned and signed arithmetic, implicit operands, and register usage.

Multiplication instructions

There are two main multiplication instructions:

  • **mul** — for unsigned multiplication
  • **imul** — for signed multiplication

Syntax examples:

mul rbx
imul rbx

Both multiply the accumulator register (a-register) by the operand.

Implicit operands

The a-register is always one operand. The second operand is specified by the programmer.

Depending on the operand size, the product is stored in two registers:

| Operand Size | Multiplicand | Product (result) | |---------------|---------------|------------------| | 8-bit | AL | AX | | 16-bit | AX | DX:AX | | 32-bit | EAX | EDX:EAX | | 64-bit | RAX | RDX:RAX |

Example (unsigned):

mov rax, 5
mov rbx, 10
mul rbx          ; RDX:RAX = 50
; RAX contains lower 64 bits, RDX contains higher bits

Signed multiplication

The imul instruction handles signed operands using two’s complement arithmetic.

Example:

mov rax, 56
mov rbx, -67
imul rbx          ; signed multiply → result in RDX:RAX

Overflow handling

Because the product can exceed the operand size, overflow is stored in the upper register (DX, EDX, or RDX). If RDX = 0 after multiplication, no overflow occurred.

Example:

mov rax, 0xFFFFFFFFFFFFFFFF   ; 2⁶⁴ − 1
mov rbx, 2
mul rbx       ; RDX:RAX = 1_FFFFFFFE (overflow)

Division instructions

Two division instructions mirror multiplication:

  • **div** — unsigned division
  • **idiv** — signed division

The dividend must be in the accumulator pair (RDX:RAX, EDX:EAX, DX:AX, or AH:AL).

After division:

  • Quotient → stored in A-register (AL, AX, EAX, RAX)
  • Remainder → stored in D-register (AH, DX, EDX, RDX)

Example (unsigned division)

mov rdx, 0        ; clear upper part
mov rax, 100      ; dividend = 100
mov rbx, 7        ; divisor = 7
div rbx            ; quotient = 14 (RAX), remainder = 2 (RDX)

Example (signed division)

mov rax, -100
cqo                ; extend sign bit from RAX into RDX
mov rbx, 7
idiv rbx           ; quotient = -14, remainder = -2

The **cqo** instruction (convert quadword to octoword) copies the sign bit of RAX into all bits of RDX, preparing the correct signed dividend.

Common pitfalls

  • Before **div/idiv**, always set or extend the upper register correctly (e.g., `xor rdx, rdx` or `cqo`).
  • Dividing by zero raises a CPU exception.
  • Overflow in multiplication affects flags (CF and OF set).

Summary

  • **mul / div** — unsigned
  • **imul / idiv** — signed
  • Use **RDX:RAX** for 64-bit operations
  • Use **cqo** before signed division
  • Check RDX for overflow and remainders

Mastering these ensures correct arithmetic handling for both signed and unsigned integers in x86-64 assembly.