In x86 assembly, most instructions have the following syntax:
operation dest, source
For example, add
looks like
add rax, 10 ; adds 10 to the rax register
But mnemonics like mul
and div
only have a single operand - source
- with the destination
being hardcoded as rax
. This forces you to set and keep track of the rax
register anytime you want to multiply or divide, which can get cumbersome if you are doing a series of multiplications.
I'm assuming there is a technical reason pertaining to the hardware implementation for multiplication and division. Is there?
The destination register of mul
and div
is not rax
, it's rdx:rax
. This is because both instructions return two results; mul
returns a double-width result and div
returns both quotient and remainder (after taking a double-width input).
The x86 instruction encoding scheme only permits two operands to be encoded in legacy instructions (div
and mul
are old, dating back to the 8086). Having only one operand permits the bits dedicated to the other operand to be used as an extension to the opcode, making it possible to encode more instructions. As the div
and mul
instructions are not used too often and as one operand has to be hard-coded anyway, hard-coding the second one was seen as a good tradeoff.
This ties into the auxillary instructions cbw
, cwd
, cwde
, cdq
, cdqe
, and cqo
used for preparing operands to the div
instruction.
Note that later, additional forms of the imul
instruction were introduced, permitting the use of two modr/m operands for the common cases of single word (as opposed to double-word) multiplication (80386) and multiplication by constant (80186). Even later, BMI2 introduced a VEX-encoded mulx
instruction permitting three freely chosable operands of which one source operand can be a memory operand.