Multiplication and Division (mul, imul, div, idiv)
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.