为什么x86架构一个字节是8个bit

2023-05-24 14:17:54 浏览数 (1)

探究计算机存储的历史:为什么x86架构下一个字节是8个bit

原文链接:Some possible reasons for 8-bit bytes

About author I’m a software developer. I live in Montreal. I sometimes give talks. Most of my income comes from my programming zines business Wizard Zines. I have one main opinion about programming, which is that deeply understanding the underlying systems you use (the browser, the kernel, the operating system, the network layers, your database, HTTP, whatever you’re running on top of) is essential if you want to do technically innovative work and be able to solve hard problems. I spent the fall of 2013 at the Recurse Center, which houses my favourite programming community. I wrote down what I did every day while there, if you want to know what it’s like.

我(我指原文作者,后文同,非译者观点!)一直在研究计算机如何用二进制表示事物的有关问题,其中有个问题被问了好几次——为什么 x86 架构使用8位字节?为什么不用其他大小呢?

对于这个问题,我认为有两种存在可能的答案:

  • 一是历史偶然,其他大小(比如4、6、16位)同样适用,不过偶然使用了8位;
  • 二是8 bit是最佳选择,即使历史发展到现在,我们仍然会使用8位作为一个字节(即原文的8-bit bytes,下文同);
  • 或者以上二者皆有。

我对计算机历史不是很了解(他更喜欢使用计算机而不是阅读相关资料),但我总是好奇为什么计算机中的这些东西现在的形式是这样的,是什么原因导致的?或者是否主要就只是历史偶然而已。所以我们来谈谈一些有关计算机的历史。

举个历史偶然的例子:DNS 有一个class字段,它有5个可能的值(“internet”、“chaos”、“hesiod”、“none”和“any”)。我认为这是一个非常明显的历史偶然例子——如果我们今天重新设计 DNS 而不需要考虑兼容性,我不敢相信我们还会以同样的方式定义 class 字段。我也不确定我们是否完全不会使用 class 字段!

这篇文章并没有给出最终答案,但我在 Mastodon 上提出了这个问题,以下是我找到的一些可能的原因,我认为最终答案是其中一些原因的组合。

byte和word的区别是什么?

首先你得知道本文中会提到的“byte”和“word”有何不同?我的理解是:

  • 字节数( byte size)是可以寻址的最小单位。例如,在我的计算机上运行某个程序时,0x20aa87c68 可能是某个字节的地址,旁边的 0x20aa87c69 就是下一个字节的地址。
  • 字大小(word size)是字节大小的某个倍数。我对这个东西困惑了很多年,而维基百科对这个概念的定义非常模糊(“ 在计算机领域, 对于某种特定的计算机设计而言,字是用于表示其自然的数据单位的术语:a word is the natural unit of data used by a particular processor design”)。最初我认为字大小(word size)与寄存器大小(register size)相同(寄存器大小在 x86-64 上为 64 位)。但是根据 Intel 架构手册(Intel architecture manual)的第 4.1 节(“基本数据类型:Fundamental Data Types”),在 x86 上,一个字(word)是 16 位,寄存器(registers)是 64 位。所以我很困惑——在 x86 上,字到底是 16 位还是 64 位?它的含义可以根据使用场景而变化吗?这是什么情况?

现在来谈一谈我们使用 8-bit bytes 的可能原因!

理由1️⃣:为了把一个英文字母放进一个字节里

下面这段维基百科中的内容称,IBM System/360 在1964年引入了8-bit bytes。

这里有一段 Fred Brooks 关于此事的视频采访(他负责管理该项目)。以下是我转录的一部分内容:

……six bit bytes实际上更适合科学计算,而8-bit byte在商业计算(commercial computing)中表现更好,而每一种都可用于另一个领域。所以选择哪一种其实是一种取决于领导的决策(executive decision),我选择了 Jerry 的 8-bit byte 提案。 […] 我在 IBM 的工作生涯中最重要的技术决策就是选择了 8-bit byte 用于IBM System/360。我相信字符处理(character processing)会变得更加重要,而不是十进制数字处理。

采用 8-bit byte 对于文本处理来说是十分合适的:2^6是64,因此6位不足以表示所有小写字母、大写字母和符号。

为了采用 8-bit byte ,System/360 还引入了 EBCDIC 编码,这是一种8位的字符编码。

8-bit byte 发展历史上影响深远的另一款设备是 Intel 8008,它被用于电脑终端(Datapoint 2200)。电脑终端需要能够表示字母以及终端控制代码(terminal control codes),所以使用 8-bit byte 也是有道理的。同时,Computer History Museum 上的这份 Datapoint 2200 手册在第7页上说明,Datapoint 2200 支持 ASCII(7位)和 EBCDIC(8位)。

为什么 6-bit byte 更适合科学计算?

我对这个评论很好奇,即为什么 6-bit byte 更适合科学计算。以下是 Gene Amdahl 接受某个采访时的一段摘录:

我之所以选择使用24-bit word和48-bit word而不是32-bit word和64-bit word,因为这样会产生一个更合理的浮点数系统。在浮点运算中,对于32位字(32-bit word),必须将指数保持在8 bits以表示指数符号,要使其有更合理的数字范围,就必须通过每4 bits进行调整而不是单个bit。因此这样会比进行二进制移位运算(binary shifting)更快地丢失信息。

我完全不理解这条评论——如果使用32位字长,为什么指数必须为8位?为什么不能使用9位或10位?但这是我找到的全部内容,如果你能解答,希望在评论区告诉我。

为什么大型机(mainframes)要使用36位字长?

与 6-bit byte 有关的另一个问题:为什么很多大型机使用36位字长?有人告诉我在维基百科上有一段关于36-bit computing的解释非常不错:

在计算机出现之前,要求及其精密的科学计算和工程计算是使用支持10位数的电动或机械计算器……这些计算器中每一位都有一列按键,操作员在输入数字时要使用所有手指,因此尽管一些专业计算器具有更多列(译者注:也就是支持不止10位数的运算),但十列确实已经基本到了极限。 因此,早期针对同一领域(译者注:指科学计算和工程计算)的二进制计算机通常使用36位字长。这足以表示正负整数的小数位达到十位(最少应为35 bits)。

因此,这个字长使用36 bit的事情似乎基于这样一个事实:log2(20000000000)为34.2。

我猜测原因是这样的。在50年代计算机非常昂贵,因此,如果想让计算机支持十个十进制数字,就需要设计计算机恰好具有足够的位数,而不再多了。

如今的计算机更快、更便宜,因此,如果我们想表示十个十进制数字,可以使用64 bits——浪费一点空间现在不是什么大问题。

还有人提到,一些具有36位字长的机器可以允许用户选择字节大小——根据使用场景可以选择5、6、7或8位一个字节。

理由2️⃣:8-bit bytes与二进制编码的十进制数一起工作效果更佳

在60年代,有一种流行的整数编码方式叫做binary-coded decimal(简称BCD),它将每个十进制数字编码为4位。

举个例子,如果你想用BCD来编码数字1234,那么就会是这样的:

代码语言:javascript复制
0001 0010 0011 0100 

因此,如果你想要能够轻松地处理二进制编码的十进制数,字节大小应该是4 bits的倍数,比如8 bits!

为什么BCD会流行呢?

我个人认为这种整数表示方法似乎非常奇怪,为什么不直接使用更高效的二进制来存储整数呢?毕竟在早期的计算机中,效率非常重要!

我的猜测是,早期的计算机没有像现在这样的显示器,所以每个字节的内容都会直接映射到了“lights”的开关上。

这是一张 IBM 650 的图片,可以看到它有一些“lights”,该图来自维基百科,(CC BY-SA 3.0):

因此,如果你能够让人们较容易地从二进制表示的数字中换算成十进制数,这就更有意义了。我认为今天BCD已经过时了,因为我们有了显示器,我们的计算机可以将用二进制表示的数字转换为十进制,并将其显示出来。

此外,我想知道“nibble”一词是否来自BCD——在BCD的时代,经常会引用半个字节(因为每个数字都是4 bits)。因此,有一个单词来表示“4 bits”,人们称为“nibble”。如今,“nibble”对我来说感觉有点陈旧了——除了作为一个趣闻之外,我肯定从来没有使用过它(这是一个非常有趣的词!)。维基百科上关于nibble的一句话支持了这个我的这个猜测:

nibble用于描述在IBM大型计算机中以压缩的十进制格式(BCD)存储数字的内存量。 The nibble is used to describe the amount of memory used to store a digit of a number stored in packed decimal format (BCD) within an IBM mainframe.

有人提到BCD的另一个原因是财务计算(financial calculations)。现在,如果你想要存储一个美元金额,通常只需要使用美分做单位存储,如果想要美元部分,就除以100。这没有什么大不了的,除法很快。但是显然,在70年代那时候,将用二进制表示的整数除以100非常慢,因此值得重新设计如何表示整数来避免除以100的效率问题。

好了,关于BCD的内容就说这么多。

理由3️⃣:8是2的幂?

许多人说将CPU的字节大小设计成2的幂是很重要的一件事。我无法确定这是否是正确的,而且“计算机使用二进制所以将字节设计成2的幂很好”这种解释并不能令我满意。这似乎非常合理,但我想深入探究。历史上确实有很多使用非2的幂大小的字节的机器,例如(来自retro computing stack exchange thread):

  • Cyber 180大型机使用6-bit bytes
  • Univac 1100/2200系列采用36位字长(36-bit word size)
  • PDP-8是一台 12-bit 机器

我还听到的一些关于使用2的幂作为字节大小是很好的理由,但是我还没有完全理解:

  • 每个 word 中的每个 bit 都需要一个总线,用户希望总线的数量是2的幂次方(为什么?)
  • 许多电路逻辑易受分而治之(divide-and-conquer)技术理念的影响(我认为我需要一个示例来理解这一点)

对我而言更有道理的原因:

  • 它使得设计可以测量“在这条线上发送了8位”的时钟分频器(clock dividers)更容易,,这些分频器的工作原理是减半(halving)——可以将3个减半(halving)的时钟分频器串联起来。 Graham Sutherland告诉我这个原因,并制作了这种时钟分频器模拟器,展示了这些时钟分频器的样子。该网站(Falstad)还有很多其他的示例电路,似乎这是一种非常酷的制作电路模拟器方法。
  • 如果您有一条指令来清除某个字节中的特定位,那么如果您的字节大小为8(2 ^ 3),则只需要使用3位指令来指示是哪个 bit 。x86似乎没有这么做,但Z80的位测试指令可以这样做。
  • 还有人提到,有些处理器使用 Carry-lookahead adders,它们以4 bit 为一组工作。从一些谷歌搜索结果来看,似乎有各种各样的加法器电路。
  • bitmaps:计算机的内存被组织成页(pages)(通常是2 ^ n的大小)。需要跟踪每页(page))是否空闲。操作系统使用 bitmap 进行此操作,其中每个bit对应于一个页面,并且根据也是否空闲表示为0或1。如果使用9-bit byte,则需要除以9才能在 bitmap 中找到所需的页面。除以9比除以2的幂次方慢,因为除以2的幂次方总是最快的方式。 我可能很糟糕地解释了一些理由。I’m pretty far out of my comfort zone here。让我们继续。
理由四:较小的字节大小是好事

你可能会想:如果8-bit bytes比4-bit bytes更好,那么为什么不继续增加byte size呢?可以使用16-bit bytes呀!

保持 byte size 较小的一些原因:

  • 这是很浪费空间的——字节是可以寻址的最小单位,如果计算机存储了大量ASCII文本(一个字符仅需要7位),那么每个字符 12 位或 16 位是非常浪费的,而可以使用8位。
  • 随着字节变大,CPU需要设计得更复杂。例如,每个位都需要一条总线线路。

所以我认为越简单越好。 我对CPU架构的理解非常不牢固,所以我就点到为止。但“这样会浪费空间”的原因对我来说感觉相当有说服力的。

理由五:兼容性考虑

Intel 8008(1972年)是8080(1974年)的前身,而8080是8086(1976年)的前身——第一个x86处理器。似乎8080和8086非常受欢迎,这就是我们现代x86计算机梦开始的地方。

我认为这里存在一个“如果它没坏,就不要修理”的问题——因为8-bit byte工作得很好,因此英特尔认为没有更改设计的必要性。如果保持相同的 8-bit byte,那么就可以重用更多的指令集。

此外,在80年代左右,我们开始使用TCP之类的网络协议,这些协议使用8-bit byte(通常称为“octets”),如果要实现网络协议,则可能要使用8-bit byte。

总结

在我看来,使用 8-bit byte 的主要原因如下:

  1. 许多早期计算机公司都是美国公司,美国最常用的语言是英语。
  2. 这些人希望计算机能够很好地处理文本。
  3. 普遍来说,较小的字节大小更好。
  4. 7位是可以将所有英文字母 标点符号都放入其中的最小大小。
  5. 8比7更好(因为它是2的幂次方)。
  6. 一旦出现流行的 8-bit 计算机并且它们运作良好,我们就希望保持相同的设计以实现兼容性。

有人指出,这本1962年的书第65页谈到IBM选择 8-bit byte 的原因基本上也是相同的。

  1. Its full capacity of 256 characters was considered to be sufficient for the great majority of applications.
  2. Within the limits of this capacity, a single character is represented by a single byte, so that the length of any particular record is not dependent on the coincidence of characters in that record.
  3. 8-bit bytes are reasonably economical of storage space
  4. For purely numerical work, a decimal digit can be represented by only 4 bits, and two such 4-bit bytes can be packed in an 8-bit byte. Although such packing of numerical data is not essential, it is a common practice in order to increase speed and storage efficiency. Strictly speaking, 4-bit bytes belong to a different code, but the simplicity of the 4-and-8-bit scheme, as compared with a combination 4-and-6-bit scheme, for example, leads to simpler machine design and cleaner addressing logic.
  5. Byte sizes of 4 and 8 bits, being powers of 2, permit the computer designer to take advantage of powerful features of binary addressing and indexing to the bit level (see Chaps. 4 and 5 ) .

f 4 and 8 bits, being powers of 2, permit the computer designer to take advantage of powerful features of binary addressing and indexing to the bit level (see Chaps. 4 and 5 ) .

总的来说,这让我觉得如果在英语国家设计一台二进制计算机,8位字节是一个自然而然的选择。

0 人点赞