对于一对有符号和无符号的数字进行算术运算是否合法?

5

我已经学习了一半的汇编语言,对于有符号和无符号整数在位上的表示方式很熟悉。我知道这可能是一个奇怪的问题,答案也很明显,但是我想知道是否可以使用像加法这样的算术运算来处理一个被认为是有符号的数字和另一个被认为是无符号的数字。我考虑了多个例子,如下所示,将产生正确的结果:

10000001(1字节整数,被视为无符号,相当于129)
+
11111111(1字节整数,被视为有符号(二进制补码系统),相当于-1)


10000000(1字节整数,在无符号逻辑中相当于128)

现在,如果上面的值在AL寄存器中,并且我们有以下指令代码(以GAS格式):

addb -1, %al

在执行操作后,如果EFLAGS寄存器的进位标志(CF)被设置,将会提示发生了溢出,但实际上并没有发生。可能是因为存在一个无符号数导致,此时应该参考EFLAGS寄存器的溢出标志(OF)。所以我不确定是否有必要这样做。

5个回答

6
数学上来讲,你不会对带符号或无符号的数字进行加法。只有模232(假设你有32位寄存器)的值存在。这些值覆盖了232个连续整数的范围,但你可以自由地将该范围解释为从任何位置开始。"带符号"和"无符号"只是其中两种解释方式。
换句话说,对于4位寄存器,"1011"的无符号解释是十一,而带符号解释是负五。但是只有一个值(数学家通常称之为"模24的十一",因为数学家传统上喜欢无符号解释)。例如,如果你将"0110"加到该值上(在带符号和无符号解释中都是"六"),那么你得到的是"0001",这是正确的值:负五加六等于一,十一加六等于十七,当减去24时也等于一(十七是一加十六;"减去24"相当于除以十六[即24]并仅保留余数)。
另一种表达方式如下:数值的二进制位数在概念上是无限的,向左延伸。CPU寄存器只保留最右边的32位。无符号解释是假设所有最左边的位都是零,带符号解释是假设所有最左边的位与第31位相同(即全部为零或全部为一)。无论哪种方式,当你执行加法(或减法或乘法)时,进位从右向左传播,而不是反过来,所以那些被忽略的位的值对32位结果没有任何影响。因此只有一个"add"操作码,它完全不关心程序员的操作数在脑海中是"带符号"还是"无符号"。
当执行与模算术不兼容的操作时,必须考虑符号。将其转换为十进制数字序列以进行显示就是这样一种操作。然而,更频繁的情况是比较。模232的值没有顺序;它们处于一种循环状态(当你将1加到232-1,并对232取模时,你回到了0)。只有当你考虑整个整数范围内的整数时,比较才有意义。此时,你必须决定是否使用带符号或无符号解释。这就是为什么x86处理器同时提供jg(带符号解释的跳转)和ja(无符号解释的跳转)的原因。

3
在二进制层面上,只有一种加法操作:
 0101 + (5)
 1010 = (unsigned 10 or signed -6)
--------
 1111   (unsigned 15 or signed -1)

那么进位标志和溢出标志呢,它们都根据简单的规则设置。如果我们将操作数视为无符号数,则可以使用CF来检测溢出;如果我们将两个操作数都视为有符号数,则可以使用OF来检测溢出。这两个标志都根据结果设置,由您决定使用哪一个。

OF标志的实际公式为

OF = CF xor MSB_of_result.

这意味着,如果我们正在加两个被视为有符号的正数,则如果结果为负数,则发生了溢出。

3
无论数字或操作是否有符号,都只是一种解释方式。当您进行加法运算时,会将两个数字相加,得到10000000,并在进位标志中放置一个1(因为它“溢出了”)。接下来的操作取决于如何解释这个结果(如果您在其他地方使用该位,则相当于不带包装的无符号加法;如果丢弃该位,则相当于进行有符号加法)。

只有当结果与所有操作数的大小相同时才是正确的。处理器通常具有乘法指令,其结果大小是操作数大小的两倍;一些处理器还具有操作数大小不同的加法指令(例如,在68000上都是ADD.W D3,A5或在TMS32050上是ADD *+将符号扩展16位值并将其添加到32位寄存器中。TMS还具有ADDU *+以将16位无符号值添加到32位寄存器中。 - supercat

1
“Signed”和“unsigned”是解释。汇编指令通常会有记录它们的解释。我不知道是否有任何架构中有一个ADD-SIGNED-UNSIGNED指令,它将其一个参数解释为有符号值,另一个参数解释为无符号值。这似乎也没有太大的价值。使用二进制补码整数算术,唯一的区别在于一些标志寄存器。

虽然处理器提供混合模式乘法指令并不常见,但是对于扩展精度有符号值的乘法运算,无论是使用专门的指令还是代码序列来实现,都需要这样的操作。 - supercat

1

我发现了这篇非常好的文章,它解决了我最关心的问题,阅读完文章后答案变得清晰明了。


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