问题描述
假设我们有:
a = 0b11111001;
b = 0b11110011;
如果我们手写Addition
和Multiplication
,我们就会得到这个结果,我们不在乎它是否签名:
a + b = 111101100
a * b = 1110110001011011
我知道乘法会使宽度加倍,加法可能会溢出:
Why is imul used for multiplying unsigned numbers?
Why do some CPUs have different instructions to do signed and unsigned operations?
我的问题是,为什么像Add
这样的指令通常没有带签名/无签名的版本,但Multiply
和Divide
有?
为什么我们不能有一个泛型unsigned multiply
,像我上面做的那样做数学运算,如果它烧焦了,就截断结果,同样的方法Add
。
或其他,为什么Add
不能有签名/未签名版本。我检查了几个架构,情况似乎就是这样。
推荐答案
我认为您选择的示例误导了您,使您认为可以通过将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只有imul
的立即数和2操作数形式,而不是mul
。只有扩大倍增才需要单独的形式。(或者如果您想要FLAGS set according to unsigned overflow of the low half, instead of signed overflow.-因此,如果您想要检测完整的无签名结果何时不符合,则不能轻松使用非加宽imul
。)