为什么有些算术指令有 signed/unsigned 变体而有些没有

Why do some arithmetic instructions have a signed/unsigned variant and some don't

假设我们有:

a = 0b11111001;
b = 0b11110011;

如果我们用手在纸上做 AdditionMultiplication 我们会得到这个结果,我们不关心它是否签名:

a + b = 111101100
a * b = 1110110001011011

我知道乘法会使宽度加倍,而加法可能会溢出:

Why do some CPUs have different instructions to do signed and unsigned operations?

我的问题是,为什么像 Add 这样的指令通常没有 signed/unsigned 版本,但 MultiplyDivide 有?

为什么我们不能有一个通用的 unsigned multiply,像我上面做的那样计算并截断结果,如果它被烧焦,与 Add 相同。

或者另一个,为什么 Add 不能有 signed/unsigned 版本。我检查了一些架构,似乎是这样。

我认为您选择的示例误导了您认为可以通过将 8x8 => 16 位无符号产品截断为 8 位来获得带符号的产品。事实并非如此。

(249-256) * (243-256) = 0x005b,一个小的正结果,恰好适合整个结果的低半部分。但是完整的带符号结果是 而不是 总是无符号乘积的操作数大小截断。

例如-128 * 127-16256,或者作为16位2的补码,0xc080.

但是0x80 * 0x7f+16256,即0x3f80。相同的下半部分,不同的上半部分。

或者另一个例子,参见Why are signed and unsigned multiplication different instructions on x86(-64)?


加宽有符号乘法不涉及任何截断。有符号和无符号乘法的低半部分是相同的,这就是为什么 x86 例如只有立即数和 2 操作数形式的 imul, not also mul. Only widening multiply needs a separate form. (Or if you want - 所以如果你想你不能轻易使用非加宽 imul检测完整的未签名结果何时不适合。)