为什么X86提供成对的除法和乘法指令?

11

我注意到,无符号整数和有符号整数在加减操作时使用相同的指令。但是在整数除法和乘法方面,有符号整数提供了idivl/imull,而无符号整数提供了divl/mull。请问这其中的原因是什么?


2
结果是不同的,所以如果没有两个版本,你会遇到麻烦。有符号和无符号的乘法低半部分是相同的,因此只有一个版本。 - harold
3个回答

10

当您进行乘法或除法运算时,结果会因参数是有符号还是无符号而有所不同。

正是二进制补码的魔力使我们能够使用相同的操作符进行有符号和无符号的加减运算。这在其他表示方法中并不成立——反码和补码都使用与无符号算术不同的加减算法。

例如,在32位字中,-10xffffffff表示。对其进行平方,有符号和无符号版本会得到不同的结果:

Signed: -1 * -1 = 1 = 0x00000000 00000001
Unsigned: 0xffffffff * 0xffffffff = 0xfffffffe 00000001

请注意结果的低位是相同的。在那些没有给出高位的处理器上,只需要一条乘法指令。在 PPC 上,有三个乘法指令——一个用于低位,另外两个用于高位,具体取决于操作数是否带符号。


在x86上,也有一些形式的imul仅提供低位字。 - harold
那个被称为pclmulqdq,所以我认为它不算是imul的一个版本。 - harold
1
@harold:我其实在想使用 and - Dietrich Epp
是的,我想是这样的,因为在我一直在看的那个中,仅存在一个低位乘法非常相关。 - harold
@YangBo:思考一下:0xffffffff ÷ 2 等于多少?对于有符号数 ((-1) ÷ 2) 和无符号数 (0xffffffff ÷ 2),答案是否不同? - Dietrich Epp
显示剩余6条评论

0
大多数微处理器使用移位加法算法(或类似算法)来实现乘法和除法。当然,这需要单独处理操作数的符号。
虽然使用加减法实现乘法和除法可以不用担心符号,从而允许可互换处理有符号和无符号整数值,但它是一种效率较低的算法,这可能就是为什么它没有被使用的原因。
我刚刚读到一些现代CPU使用Booth编码方法,但该算法也意味着要确定值的符号。

1
也许值得添加一些注释来对比一下加法和减法,无论输入是否带符号,都可以直接进行(只需要设置溢出标志以帮助后续处理)。 - Damien_The_Unbeliever
@Damien:你说得很对;问题确实提到了加法和减法,这暗示了“加减”的概念。请看我的编辑。我正在寻找有关CPU基本算术运算实现选择起源的信息,但迄今没有找到“权威”的资料。 - mjv

0

在x86中,如果我们谈论整数和无符号整数,符号存储在字的高位。 ADD和SUB命令使用一种算法来处理有符号和无符号的情况,可以得到正确的结果。

但是对于MULL和DIV,这种方法不适用。您需要“告诉”CPU您想要“使用”有符号或无符号的int。 对于无符号,请使用MULL和DIV。它只操作字 - 这很快。 对于有符号,请使用MULL和IDIV。它将字转换为绝对(正)值,将符号存储为结果,然后执行操作。这比MULL和DIV慢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接