内存地址对齐

时间:2012-04-04 20:36:50

标签: memory assembly operating-system

我对内存对齐的概念感到有点困惑。所以这是我的疑问: 文本说的是,如果你想要读取4个字节的数据,从一个不能被4整除的地址开始,就会有一个未对齐的内存访问的情况。例如,如果我想读取从地址05开始的10个字节,这将被称为未对齐访问(http://www.mjmwired.net/kernel/Documentation/unaligned-memory-access.txt)。

这种情况是否特定于4字节字可寻址架构,或者这对于字节可寻址架构是否有效?如果上述情况没有对齐字节可寻址架构,为什么会这样呢?

谢谢!

2 个答案:

答案 0 :(得分:3)

作为一般规则,存储器中的位0被门控到总线上,该总线的第0位连接到每个寄存器的第0位。它一直持续到第31位。可能有特殊的硬件将每个字节(位15:8,23:16和31:24)指向低位字节,位7:0。 (当你到位“32”时,它实际上是地址4的4字节字的第0位。)

但是,在名义上的情况下,有任何特殊硬件将字节移动到除了它们以自然顺序名义连接的位置之外的任何位置,并且可能是字节通道0。 / p>

想象一个简单的存储芯片,带有32个数据引脚和一个带有32个数据引脚的简单CPU。每个芯片上的给定数据引脚连接到另一个芯片上的相应数据引脚,并且仅连接到那个芯片上。对于一个简单的CPU来说,根本没有 来完成未对齐的读取

所以,考虑从0开始读取。接下来的4个字节全部落入有线的寄存器中,这也适用于从地址4读取。但是,如果从地址1读取(32位)怎么办?还是2?还是3?尽管读取不能直接在硬件中完成,但是花哨的控制器可能会导致很多事情发生:

  • CPU只能执行两次读取以获取所有位。它不能同时做它们,它只有32个引脚。一次读取来自地址0,一次来自地址4
  • 然后CPU必须执行各种shift,mask和inclusive-OR操作,以便从这两个组件中构造一个单词。

所有这些都需要额外的时间。


注意。实际上,数据总线通常是32位的倍数,因此存储器也是如此。可能存在用于重新对齐对象的特殊硬件。但即便如此,因为它是一个异常情况,它可能无法获得正确对齐读取的流水线优化,即使使用特殊硬件,运行操作数也可能会有时间损失。

答案 1 :(得分:1)

对齐与数据大小和寻址有关。大多数指令集/软件的寻址以字节为单位。 0,1,2,3都是有效的字节地址。假设您正在访问的内存系统或外围设备是“字节可寻址”,基本上您可以为其写入单个字节,通常您可以使用允许您使用任何地址值的指令。当你有多个字节,两个字节时,对齐开始,如果对齐则意味着地址的lsbit为零,未对齐意味着它是一个。四个字节,32位量,低两位为零,对齐,一个或两个不为零,未对齐,依此类推。可以把它想象成你想要一个模4 = 0的地址在4字节边界上对齐的模数。

现在通常作为一名软件工程师,你不会故意让自己处于需要在地址5处获得10个字节的情况下,你可能会在0x4处执行12个字节或在0x0处执行16个字节,或者沿着这些线执行某些操作,即使您只使用其中的10个,你可以更逻辑地对齐它们。外部影响,网络数据包,文件系统,共享内存,硬件等,只要您跨越编译域,您可能必须处理此问题并采取相应措施。 10个字节是半有趣的取决于你是否试图将这些字节复制到另一个同样糟糕的地址或只是读取或写入它们。如果读取你可能只想在地址0x4读取12个字节并完成它。如果写得好,你可以在一个漂亮的循环中完成所有10个或一次展开一个字节,你可以写一个在0x5,两个在0x6,四个在0x8,两个在0xC和一个在0xE,或一个在0x5,a循环或展开4个16位值,从0x6开始,然后在0xE处一个字节。等等。

由于您说读取时您可以读取0x4处的3个32位数量或从0x0处读取的两个64位数量。它在很大程度上取决于您计划对数据执行的操作以及您正在使用的指令集等.10字节读取循环可能是最简洁/最简单的读取,维护等。

如果你想知道对齐vs未对齐那么就像我上面提到的写一样,你可以做一个

8 bit access at 0x5
16 bit access at 0x6
32 bit access at 0x8
16 bit access at 0xC
8 bit access at 0xE

正如我一直在说的那些可能不是最有效的读物。对于写入,您可以读取 - 修改32或64位数量的写入或我上面提到的组合。