4.1 内存
计算机需要一个地方来保存它们正在操作的位。我们在第3章中介绍过,那个地方就是内存。现在来看计算机使用内存的原理。
内存就像是一条建满了房屋的长街。每间房子大小完全一样,都有容纳一定数量位的空间。编译代码基本上都是按每间房子1个字节计算的。就像在真正的街上一样,每个房子都有一个地址,每个内存都有对应的数字。如果计算机内存为64 MiB,则包含64×1 024×1 024=67 108 864字节(或536 870 912位)。字节的地址为0到67 108 863。与建筑物门牌号不同,字节的地址有实际的用处。
引用内存位置很常见,引用内存位置即引用特定地址的内存,比如内存通道3(见图4-1)。
图4-1 内存通道
内存的基本单位是字节,这并不意味着我们总是按单个数量来处理字节。例如,32位计算机通常将内存组织成4字节块,而64位计算机通常将内存组织为8字节块。4字节块和8字节块区别很大吗?这就像四车道或八车道的高速公路,更多的车道可以解决更严重的交通拥堵,因为更多的位可以进入数据总线。寻址内存时,我们需要知道我们在寻址什么。寻址长字与寻址字节是不同的,因为在32位计算机上,一个长字有4个字节,而在64位计算机上有8个字节。例如,在图4-2中,长字地址1包含字节地址4、5、6和7。
图4-2 内存高速路
从另一个角度来看,32位计算机中的内存包含四个单元,而不是单个单元,每个单元包含两个双路复用器。这意味着我们可以寻址单个单元、双路复用器或整个构件。
你可能已经注意到,每栋大楼都横跨“高速公路”,因此每个字节都有自己指定的通道,而一个长字就占据了整个道路。位每天乘坐一辆有四个座位的“巴士”往返于市中心,每个字节都有一个座位。车门的设置使得每条车道都有一个座位。在大多数现代计算机上,从市中心出发的“巴士”只在一座大楼前停留。这意味着我们不能从字节5、6、7和8中组成一个长字,因为这需要市中心出发的“巴士”进行两次行程:一次行驶到1号楼,一次行驶到2号楼。过去的计算机中有一个复杂的装卸平台,允许“巴士”这样做,但是规划者也注意到往返两次这点并不是那么实用,所以在新型号的计算机中削减了它的预算。现在的计算机中的“巴士”试图同时进入两个建筑物,如图4-3所示,称为非对齐访问。
图4-3 对齐和非对齐访问
正如我们在上一章中看到的,计算机中有很多不同种类的存储器。每一种的性价比都不同。例如,SRAM虽快但贵,就像行驶在政客们居住处附近的高速公路一样。磁盘倒是便宜,可慢得像行驶在泥泞的土路。
“巴士”上哪个字节坐哪个座位?当一个长字坐车进城时,字节0或字节3会坐在最左边的座位上吗?答案取决于你所使用的处理器,因为设计师们已经把两种方式都做到了,字节0或3都可以坐到最左边的座位上。两种方式都有效,几乎像神学辩论一样魔幻。事实上,在Jonathan Swift的《格列佛游记》中,基于小人国和大人国皇家法令的术语端,就被用来描述这种区别。
字节0在英特尔处理器这样的小端机器中占据“巴士”最右边的位置,在摩托罗拉处理器这样的大端机器中占据“巴士”最左边的位置。图4-4比较了这两种排列。
图4-4 大小端式排列
字节顺序是在将信息从一个设备传输到另一个设备时要记住的一点,因为你不希望无意中将数据打乱。在将UNIX操作系统从PDP-11移植到IBM系列/1计算机时,就有这样一个值得注意的例子:当16位字中的字节被交换时,一个本应输出“Unix”的程序却输出了“nUxi”。这也够滑稽的,nuxi综合征就是指这种字节排序问题。