负数在内存中以2的补码形式存储,CPU如何知道它是负数还是正数?
-1可以用4位二进制表示为(2的补码)1111
15也表示为1111。
那么,CPU从内存获取值时如何区分15和-1呢?
-1 can be represented in 4 bit binary as (2's complement) 1111
15 is also represented as 1111.
So, how does CPU differentiate between 15 and -1 when it gets values from memory?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当CPU从一个地方移动到另一个地方时,CPU并不关心一个字节是-1还是15。不存在所谓的“签名移动”(到相同大小的位置 - 对于更大或更小的目的地有签名移动)。
CPU 仅在对字节进行算术运算时关心表示形式。 CPU 根据您(或代表您的编译器)选择的操作码知道是否执行有符号或无符号算术。
The CPU doesn't care whether a byte holds -1 or 15 when it moves it from one place to another. There's no such thing as a "signed move" (to a location of the same size - there is a signed move for larger or smaller destinations).
The CPU only cares about the representation when it does arithmetic on the byte. The CPU knows whether to do signed or unsigned arithmetic according to the op-code that you (or the compiler on your behalf) chose.
之前的大多数答案都提到了单独的操作码。对于乘法和除法等更复杂的运算来说可能是这样,但对于简单的加法和减法来说,这不是 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 为你提供了区分它们所需的工具,但它本身并不区分。
Most of the previous answers mentioned separate opcodes. That might be true for more complicated operations like multiplication and division, but for simple addition and subtraction that is not how the CPU works.
The CPU keeps data about the result of an instruction in its flags register. On x86 (where I am most familiar) the two most important flags here are the "overflow" and "carry" flags.
Basically the CPU doesn't care if the number is signed or unsigned it treats them both the same. The carry flag is set when the number goes over the highest unsigned value it can contain. The overflow flag is set when it goes over or under the range of an unsigned number. If you are working with unsigned numbers you check the carry flag and ignore the overflow flag. If you are working with signed numbers you check the overflow flag and ignore the carry flag.
Here are some examples:
Unsigned:
1111 (15) + 1111 (15) = 1110 (14)
What you do now is check the carry flag, which in this case contains one giving the final result
1 1110 (30)
Signed:
1111 (-1) + 1111 (-1) = 1110 (-2)
In this case you ignore the carry flag, the overflow flag should be set to zero.
Unsigned:
0111 (7) + 0111 (7) = 1110 (14)
When you check the carry flag it should be zero.
Signed:
0111 (7) + 0111 (7) = 1110 (-2)
In this case the overflow flag would be set meaning that there was an error in the addition.
So in summary the number is only signed or unsigned based on your interpretation of it, the CPU gives you the tools nessecary to distinguish between them, but doesn't distinguish on its own.
CPU 不知道一个数字是有符号的还是无符号的。当编译器创建机器语言文件时,它会选择要执行的正确操作以对该数字进行数学运算。例如,如果您将变量声明为有符号类型,则以机器语言执行的操作将将该内存位置视为有符号值。
在任何类型的任何软件中,总是在您解释数据时才赋予其含义。内存中的字节可以是有符号或无符号的数字、字符、音乐文件的一部分、图片中的像素等。赋予它意义的是您如何使用该字节。
The CPU doesn't know if a number is signed or unsigned. When the compiler creates the machine language file, it chooses the correct operation to be executed to make a math operation with that number. If you declared your variable to be of the signed type, for instance, than the operation to be executed in machine language will be one that treats that memory position as a signed value.
In any software of any kind, it is always when you interpret the data that you give it meaning. A byte in memory can be a signed or unsigned number, or a character, or a part of a music file, or a pixel in a picture, etc. What gives it meaning is how you use that byte.
在编译器级别,区分是基于数据类型的。如果数据类型为 int,则为该变量分配 4 个字节(在 C 中)。因此 2 的补码中的 15 是
00000000 00000000 00000000 00000000 00001111
,而 -1 是11111111 11111111 11111111 11111111
。然后编译器将其转换为 CPU 相应的操作码。 CPU 执行该操作码,在此级别,所有内容均采用 1 和 0 的形式。At the compiler level, the differentiation is based on data type. If the data type is int, then 4 bytes is allocated to that variable (in C). So 15 in 2's complement is
00000000 00000000 00000000 00000000 00001111
while -1 is11111111 11111111 11111111 11111111
. The compiler then converts this to the corresponding opcode of the CPU. The CPU executes this opcode and at this level everything is in the form of 1s and 0s.在 2 的补码中表示 15,我们需要 5 位,2'补码的范围是
-16到15,所以值变成01111这里MSB位是0所以它的正值-1它将变成11111
In 2's complement to represent 15 we require 5 bits the range for 2'complemnt is
-16 to 15,so the value become 01111 here the MSB bit is 0 so its positive value for -1 it will become 11111