32位处理器如何支持64位整数?

15

在C++中,你可以使用一个通常为4个字节的int。一个long long整数通常是8个字节。如果CPU是32位的,那么不会限制32位数字吗?如果它不支持64位,我怎么能使用long long整数? ALU是否可以添加更大的整数或其他内容?


请参阅 Knuth Vol 2,第4.3节。 - brian beuning
在32位机器上如何实现64位数学运算? - phuclv
5个回答

25

大多数处理器都包括进位标志位和溢出标志位,以支持对多字节整数的操作。进位标志位用于无符号运算,而溢出标志位用于有符号运算。

例如,在x86上,您可以像这样添加两个无符号64位数字(我们假设它们在EDX:EAX和EBX:ECX中):

add eax, ecx  ; this does an add, ignoring the carry flag
adc edx, ebx  ; this adds the carry flag along with the numbers
; sum in edx:eax

在像C++这样的高级语言中也有可能实现这种东西,但它们对此的支持要少得多,因此代码通常比用汇编语言编写时慢得多。

大多数操作基本上是按顺序进行的。当您以二进制级别进行加法运算时,您需要取两个输入位并产生一个结果位和一个进位位。然后在添加下一个最低有效位时,将使用进位位作为输入,并依此类推(称为“涟漪加法器”,因为加法在整个字中“涟漪”传递)。

有更复杂的方法可以执行加法,可以减少在特定加法不产生依赖性时一个比特与另一个比特之间的依赖性,大多数当前的硬件都使用这些方法。

但在最坏的情况下,向已经是给定字大小支持的最大数字添加1将导致从每个位到下一个位生成一个进位,一直到整个字为止。

这意味着(至少在某种程度上),CPU支持的字宽限制了它可以运行的最大时钟速度。如果有人非常想这样做,他们可以构建一个使用1024位操作数的CPU。如果他们这样做,他们就有两个选择:要么以较低的时钟速度运行它,要么需要多个时钟来添加单个操作数对。

另请注意,随着扩展这样的操作数,您需要更多的存储空间(例如更大的高速缓存)来存储尽可能多的操作数、更多的门来执行每个单独的操作等等。

因此,在相同的技术条件下,您可以拥有一个64位处理器,它以4 GHz的速度运行,并具有4兆字节的高速缓存,或者一个以大约250 MHz的速度运行并具有2兆字节高速缓存的1024位处理器。

如果您的工作中大部分都是在1024位(或更大)操作数上进行,则后者可能会获胜。但是,大多数人几乎从不对1024位操作数进行数学计算。实际上,64位数字对于大多数目的已经足够大了。因此,对更宽的操作数提供支持可能通常会导致大多数人在大多数情况下产生净损失。


那么为什么计算机不能拥有128位整数?甚至256位呢?我知道有相应的类可以实现,但为什么计算机本身就不能做到呢? - user3452725
4
他们可以,你只需要通过链接这些传递指令来告诉他们。 - Mysticial
4
添加基本上是一种串行操作——添加两个最不重要的位会生成一个结果位和一个进位位,该进位位会在添加下一个最不重要的位时用作输入。有优化方法可以减少这种依赖性,但在最坏的情况下,您可能需要一直进行进位,因此这是不可避免的。因此,虽然它们可以支持单次操作中的更宽字长,但这样做会降低速度,而且大多数人很少使用128位或256位数字。减法、乘法等也有类似的考虑。 - Jerry Coffin

5

即使底层硬件只支持较少的位数,也可以通过软件实现来支持任意宽度的整数。如果将32位整数加上另一个32位整数,可能会溢出并需要33位来存储答案。软件可以检测到发生了这种溢出(处理器有一个进位标志可以被检查),并且表示64位数字的最高有效位的另一个32位字可以增加1。

这里更详细地介绍了进位标志及其使用方法。


5

基本上,通常的单指令加法被分成了两个(或三个)步骤:

1)使用通常的加法指令添加低位32位。请注意,此加法是否会生成“进位”位(即,如果结果实际上需要33位来表示)。

2)以相同的方式添加高位32位。如果从低位比特中有一个进位,则在此处设置进位输入比特(或者,在添加后将结果加一)。


4

您需要使用两个内存地址来存储这个数。这个数的一半被存储在内存中的一个地址,而另一半则存储在相邻的内存地址。


那取决于你想做什么。比如说你要相加两个数字:你先相加低位部分,然后再加上高位部分和任何产生的进位。 - Outsider
如果你想了解更多,学习汇编代码可能是一个不错的主意。 - Outsider
1
@user3452725 整数无法四舍五入,因为它们总是一个整数。 - Steve
@Steve 抱歉,我的意思是携带。 - user3452725

2
你可能要考虑,早在 8 位 CPU 的时代,我们就已经处理过 16 位甚至 32 位大小的整数。除了内存空间和用户的耐心外,没有任何限制特定 alu 处理任意大小的数字。
比如 Smalltalk 自原始 Dorados 和 Altos 开始就一直提供任意长度的整数——这可以追溯到 1970 年。想要精确计算 963! 的值——只需要计算即可。然而,将其格式化为可打印的形式可能需要一些时间。

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