冯诺依曼体系的计算机,通过地址总线来寻址内存(假设 n 为地址总线的位数,则最多可以寻址 2n 个内存位置)。根据地址总线的位数,我们可以知道 CPU 与内存的一次交互(也即一次内存访问)能够读写的数据的大小。显然地,对于 8 位的 CPU ,是一个字节,对于 16 位 CPU 则是一个字, 32 位 CPU 则是一个双字,依此类推。这是 CPU 与生俱来的最本质、最快捷的访问方式。在实际的计算需求中,如果访问的数据量超过了一次访问的限度,则很显然需要进行多次访问,如果是少于的话,则需要对从内存中取回的数据进行适当的裁剪。裁剪操作有可能是 CPU 自身支持的,也有可能是需要用软件来实现的。
有的系统是支持寻址到单个字节所在的位置的(称为可字节寻址),而有的则不可以,只能寻址到符合某些条件的地址上。对于 Intel/ARM 体系结构的 CPU ,我们在宏观上可以认为它们都支持字节寻址(但是 ARM 家族的 CPU 在内存访问时有其他约束,下文有详细叙述)。
出现这样的限制是有原因的,终极因素就在于内存访问的粒度与字长的关联上。用 32 位 CPU 来说,它对于地址为 4 的倍数处的内存访问是最自然的,其余的地址就要做一些额外的工作。例如,我们要访问地址为 0x03 处的一个双字,对于 80x86 体系,事实上将会导致 CPU 的两次内存访问,取回 0x00 以及 0x04 处的两个双字,分别进行适当的截取之后再拼装为一个双字返回。对于其他的体系,设计者可能认为 CPU 不应该承担数据拼装的工作,因而就选择产生一个硬件异常。
效果最好的努力是 Intel 的体系架构。 80x86 允许你对整个内存进行字节寻址,在不超过机器字长的情况下可以访问任意数目的字节(很显然,大多数情况下就是 1 字节、 2 字节、 3 字节、 4 字节这四种情况)。ARM 体系的 CPU 似乎做了一定的努力,但是其结果和其他体系相比呈现一种很奇怪的状态。由于笔者没有对 ARM 整个系列的 CPU 进行过完整的了解,因此此处的论述可能并不完整。 ARM CPU 允许对内存进行字节寻址,但在访问时有额外的要求。即:如果你要访问一个字(注意本文惯例,此处的字是两字节大小,与 ARM 平台的标准术语不同),那么起始地址必须在一个字的边界上,如果访问一个双字,则起始地址必须位于一个双字的边界上(其余数据类型请参考 ARM 的知识库文档)。这意味着,你不能在 0x03 这样的地址处访问一个字或者一个双字。但是,令人痛苦的事情到来了,如果你非要这么访问,大多数的 CPU 不会有显式的异常,而是返回错误的数据,其余的一些 CPU 则会造成程序崩溃。