I thought the whole point of 2's complement was that operations could be implemented the same way for signed and unsigned numbers. Wikipedia even specifically lists multiply as one of the operations that benefits. So why does x86 have separate instructions for each, mul
and imul
? Is this still true for x86-64?

- 10,435
- 4
- 39
- 71

- 20,727
- 18
- 94
- 165
-
See also [problem in understanding mul & imul instructions of Assembly language](https://stackoverflow.com/a/19783509) re: different forms of multiply, including `imul reg, r/m` instead of the one-operand widening form. And also [How many least-significant bits are the same for both an unsigned and a signed multiplication?](https://stackoverflow.com/a/72309286) – Peter Cordes May 22 '22 at 18:26
3 Answers
Addition and subtraction are the same, as is the low-half of a multiply. A full multiply, however, is not. Simple example:
In 32-bit twos-complement, -1 has the same representation as the unsigned quantity 2**32 - 1. However:
-1 * -1 = +1
(2**32 - 1) * (2**32 - 1) = (2**64 - 2**33 + 1)
(Note that the low 32-bits of both results are the same; that's what I mean when I say the "low-half of the multiply" is the same).

- 103,815
- 19
- 183
- 269
-
1For what range of operands can I expect mul and imul to give bitwise identical results? When both operands are positive and their result doesn't exceed 2 ** 63 - 1? (that is, when unsigned result is too small to flip sign bit) – Joseph Garvin Dec 28 '12 at 02:20
-
9@JosephGarvin: No, as soon as you go even one bit over the original length, you need separate instructions. Consider e.g. `-1 * 1 = -1` vs. `0xFFFFFFFF * 1 = 0xFFFFFFFF`. – Ilmari Karonen Dec 28 '12 at 02:40
-
3as the low half of the result is the same and C programs often produce results with the same size as the operands, modern x86 CPUs are often [optimized for imul](http://stackoverflow.com/a/4040834/995714) and it has many more forms (`imul rs, rd1[, rd2]`) while mul has only 1 form `mul rx` – phuclv Mar 06 '14 at 14:44
-
2the high half of the result is different in signed and unsigned version but they [do have a relation](http://stackoverflow.com/a/28827013/995714) so it's possible to get a high unsigned result from a high signed result and vice versa – phuclv Dec 02 '16 at 02:59
-
This answer states differently: https://softwareengineering.stackexchange.com/a/358203/297215 – plasmacel Jun 25 '18 at 12:06
-
2
-
2@plasmacel: Correct, that [answer you linked](https://softwareengineering.stackexchange.com/a/358203/297215) is assuming a non-widening multiply like in C, which that question is tagged with. In C if you want a uint64_t product, you need `a * (uint64_t)b` if the inputs are narrower. It doesn't match reality for asm with widening multiply instructions. – Peter Cordes May 22 '22 at 18:31
The result will be the same for the 2 and 3 operand versions except that the mul and imul instructions differ in how they set the CF and OF flags (carry and overflow).
Think of the two cases: -1 * -1 versus 0xFFFFFFFF * 0xFFFFFFFF in terms of overflow and you'll get the idea.

- 133
- 1
- 4
-
1There isn't a 2 or 3-operand version of [`mul`](https://www.felixcloutier.com/x86/mul). The only difference *would* be FLAGS setting, but that's needed rarely enough that Intel decided to only provide faster non-widening multiply as [`imul`](https://www.felixcloutier.com/x86/imul) opcodes. Related: [C unsigned long long and imulq](https://stackoverflow.com/a/38254324) hinges on this decision: if you want an overflow-checked unsigned multiply, you unfortunately want one-operand `mul` instead of trying to do something with FLAGS from `imul reg,reg`. – Peter Cordes May 08 '21 at 18:46
Multiplication of two 16-bit numbers yields a 32-bit result. Even if one of the numbers is "1", the processor will effectively extend the other to 32 bits. The process of extending a number to a longer bit length is one of the operations which is different for signed and unsigned values (the other significant operation where sign matters is magnitude comparison, which is also an essential part of division).

- 77,689
- 9
- 166
- 211