Search code examples
assemblyx86x86-64instruction-setinstructions

Why do x86 mul and div instructions only take a source operand?


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?


Solution

  • 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.