Instructions
x86-64IMUL / MUL
MUL is unsigned widening multiply; IMUL is the signed (and most compiler-used) form with one-, two-, and three-operand variants.
x86-64 has two multiply instructions. MUL is always unsigned and widens the
result; IMUL covers signed multiplication and has flexible non-widening forms
that compilers prefer.
MUL — one operand, unsigned widening
mul rbx ; RDX:RAX = RAX * RBX (128-bit result)
mul ecx ; EDX:EAX = EAX * ECX (64-bit result)The result is always twice the operand width. CF and OF are set if the high half is non-zero.
IMUL — signed, three forms
; One operand (widening, signed) — mirrors MUL behaviour
imul rbx ; RDX:RAX = RAX * RBX (signed 128-bit)
; Two operands (truncating) — most common in compiled code
imul rax, rbx ; rax *= rbx (lower 64 bits only)
imul rax, rcx ; rax *= rcx
; Three operands (immediate) — very common
imul rax, rbx, 10 ; rax = rbx * 10
imul rcx, rcx, 0x24 ; multiply immediate (struct stride, etc.)CF and OF are set if the result was truncated (i.e. the full signed product does not fit in the destination).
Compiler patterns
| Source | Assembly |
|---|---|
a * b (int) | imul eax, esi |
a * 12 | imul rax, rdi, 12 or lea-based equivalent |
a * constant (non-power-of-2) | imul rax, rdi, K |
| Cryptographic wide multiply | mul rsi + add rdx, ... |
Reverse-engineering notes
- Compilers almost never emit
mulfor high-level C integer multiplication — they useimulwith two or three operands even for unsigned types because the low word of a signed and unsigned multiply is identical. - Seeing
mul(one-operand form) usually means big-integer arithmetic, modular exponentiation, or a deliberate 128-bit product (e.g.__int128or cryptography). - When reversing loop stride:
imul rcx, rdx, sizeof_structis often the multiplication to find the Nth element of an array of structs. - CF=OF=0 after
imulmeans the result fits in the destination size with no overflow — useful for detecting overflow-check logic in safe-integer code.