22

-1 可以用 4 位二进制表示为(2 的补码)1111

15 也表示为 1111。

那么,当 CPU 从内存中获取值时,它如何区分 15 和 -1 呢?

4

6 回答 6

18

当一个字节从一个地方移动到另一个地方时,CPU 并不关心它是保持 -1 还是 15。没有“签名移动”之类的东西(到相同大小的位置 - 有更大或更小的目的地的签名移动)。

CPU 仅在对字节进行算术运算时才关心表示。CPU 根据您(或代表您的编译器)选择的操作码知道是进行有符号还是无符号运算。

于 2011-10-06T22:15:11.043 回答
10

以前的大多数答案都提到了单独的操作码。对于像乘法和除法这样的更复杂的操作,这可能是正确的,但对于简单的加法和减法,这不是 CPU 的工作方式。

CPU 将有关指令结果的数据保存在其标志寄存器中。在 x86(我最熟悉的地方)上,这里最重要的两个标志是“溢出”和“进位”标志。

基本上,CPU 并不关心数字是有符号还是无符号,它会将它们都视为相同。当数字超过它可以包含的最高无符号值时,设置进位标志。当超出或低于无符号数的范围时设置溢出标志。如果您使用无符号数,请检查进位标志并忽略溢出标志。如果您使用带符号的数字,请检查溢出标志并忽略进位标志。

这里有些例子:

未签名:

1111 (15) + 1111 (15) = 1110 (14)

你现在要做的是检查进位标志,在这种情况下,它包含一个给出最终结果的标志

1 1110 (30)

签:

1111 (-1) + 1111 (-1) = 1110 (-2)

在这种情况下,您忽略进位标志,溢出标志应设置为零。

未签名:

0111 (7) + 0111 (7) = 1110 (14)

当您检查进位标志时,它应该为零。

签:

0111 (7) + 0111 (7) = 1110 (-2)

在这种情况下,溢出标志将被设置,这意味着添加中存在错误。

因此,总而言之,该数字仅根据您对它的解释是有符号或无符号的,CPU 为您提供了区分它们的必要工具,但它本身并不能区分。

于 2014-06-22T17:22:12.283 回答
7

CPU 不知道一个数字是有符号的还是无符号的。当编译器创建机器语言文件时,它会选择要执行的正确操作来对该数字进行数学运算。例如,如果您将变量声明为有符号类型,那么在机器语言中执行的操作将把该内存位置视为有符号值。

在任何类型的任何软件中,总是在您解释数据时赋予它意义。内存中的一个字节可以是有符号或无符号数字、字符、音乐文件的一部分或图片中的像素等。赋予它意义的是您如何使用该字节。

于 2014-06-22T16:04:20.337 回答
2

在编译器级别,区分基于数据类型。如果数据类型是 int,则为该变量分配 4 个字节(在 C 中)。所以 2 的补码中的 15 是00000000 00000000 00000000 00000000 00001111,而 -1 是11111111 11111111 11111111 11111111。然后编译器将其转换为 CPU 的相应操作码。CPU 执行这个操作码,在这个级别上,一切都是 1 和 0 的形式。

于 2011-10-06T22:08:41.553 回答
0

最小的可访问单元是 1 个字节。那是8位。在 8 位表示中,15 存储为 00001111。编译器根据符号位区分正数和负数。MSB 是符号位。如果为 0 表示正数。如果是 1 表示负数。15的二进制表示的MSB为0,表示正数,00001111对应+15。-1 的 8 位二进制是 11111111,因为它的 MSB 为 1,它被取为负数。编译器首先取其 2 的补码,然后显示带有负号的数字。请记住,如果有 8 位来存储数字,那么您可以在其中存储的最大值是 (2^7)-1,它的表示形式需要 7 位。这意味着对于正数,MSB 始终为零。正如您的问题一样,如果我们假设使用 4 位来存储数字,那么 3 位可用于存储该值,因为最后一位是保留符号的保留位。对于 3 位,可以存储的最大值为 (2^3)-1=7。这意味着 15 不能存储在 4 位中。因此 1111 总是被编译器视为 -1。

请按照以下链接访问存在此类棘手问题的 YouTube 频道。www.YouTube。com/watch?v=ZxRHOT3pzx4

于 2016-08-12T09:43:19.617 回答
0

在表示 15 的 2 的补码中,我们需要 5 位 2' 补码的范围是 -16 到 15,所以值变成 01111 这里 MSB 位是 0 所以它的正值 -1 它将变成 11111

于 2016-12-23T18:09:37.643 回答