为什么有些算术指令有带符号/无符号的变体,而有些没有

人气:423 发布:2022-10-16 标签: cpu cpu-architecture instruction-set integer-arithmetic

问题描述

假设我们有:

a = 0b11111001;
b = 0b11110011;

如果我们手写AdditionMultiplication,我们就会得到这个结果,我们不在乎它是否签名:

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这样的指令通常没有带签名/无签名的版本,但MultiplyDivide有?

为什么我们不能有一个泛型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。)

951