数据对齐:限制内存地址为数据类型大小的倍数的原因

Data Alignment: Reason for restriction on memory address being multiple of data type size

我了解数据对齐的一般概念,但我不明白的是对内存地址值的限制,强制为基础数据类型大小的倍数。

This answer 很好地解释了数据对齐。

引用:

Let's look at a memory map:

+----+
|0000| 
|0001|
+----+
|0002|
|0003|
+----+
|0004|
|0005|
+----+
| .. |

At each address there is a byte which can be accessed individually. But words can only be fetched at even addresses. So if we read a word at 0000, we read the bytes at 0000 and 0001. But if we want to read the word at position 0001, we need two read accesses. First 0000,0001 and then 0002,0003 and we only keep 0001,0002.

问题:

假设是真的,为什么“但是只能在偶数地址取词。”是真的吗? memory/stack 指针不能指向示例中的 0001,然后从那里开始读取一个字的信息吗?

我们知道机器可以通过一次读取操作以 2 个字节为单位读取内存(在示例 [0000, 0001] 或 [0002, 0003] 中)。因此,如果我的地址寄存器指向 0001(奇地址而不是偶地址),那么我可以在一次读取操作中直接从那里读取 2 个字节(即 0001 和 0002),对吗?

关于该陈述的假设不一定正确。我不想重复您链接到描述使用和高度偏好对齐访问的原因的答案,但有些架构确实支持未对齐的内存访问——例如 ARM(查看此 ) .

但我认为你的问题实际上归结为硬件架构,特别是数据总线设计,以及各个硅制造商的工程师设计的附带指令集。


某些 Cortex-M 内核明确允许您启用 CPU 通过配置 Usage Fault 寄存器在 un- 对齐访问上触发异常,这意味着在极少数情况下,您可以"utilize" 未对齐的内存访问。

通常处理器内部地址指向一个完整的字。这是因为您不希望您的(简单)处理器能够以随机字节(或更糟:位)寻址一个字,因为

  1. 你浪费了可寻址内存:假设你的处理器能够处理的最大可能地址是它的字长的最大值,你可以用它乘以你的字长来计算数量您可以解决的存储空间。 (每个唯一地址指向一个完整的单词)我在这里谈论的 "address" 不一定看起来像可能存储在高级编程语言的指针中的地址。指针地址寻址每个字节,将由编译器或解释器解释成相应的汇编指令(从加载的字中丢弃不需要的字节)

  2. 从内存中加载的单词可以是任何东西,一个值或您处理器上 运行 程序的下一条指令 - 加载到处理器中的前一个单词通常会给出一个指示被加载的以下字的用途:另一条指令(例如算术运算、加载或存储指令),其后可能跟有操作数(值或地址)。能够处理未对齐的字会使处理器复杂化很多。

Assuming it's true, why " But words can only be fetched at even addresses. " be true?

内存实际上存储的是单词。处理器实际上以字为单位寻址内存,一次取一个字。

当您获取一个字节时,它实际上是获取一个字,然后忽略前半部分或后半部分。

在 32 位处理器上,它获取一个 32 位字,然后忽略四分之三;在 32 位处理器上获取 16 位字会忽略一半字。

如果您要获取的 16 位字(在 16 位处理器上)未对齐,则处理器必须获取两个字,取每个字的一半,然后重新组合它们。因此,即使在它工作的处理器设计上,它通常也比较慢。

很多处理器设计都不会打扰 - 它们要么不允许,要么强制操作系统处理它(这非常慢)。

(并非所有类型的处理器都以这种方式工作 - 例如,8 位处理器通常一次获取一个字节)

Can't the memory/stack pointer point to 0001 in the example and then read a word of information starting there?

如果处理器支持,是的。