5

我需要从现有的 64 位值中提取一个内存地址,该地址指向一个 4K 数组,起始值为:

0x000000030c486000

我需要的地址存储在位 51:12 中,因此我使用以下方法提取这些位:

address = start >> 12 & 0x0000007FFFFFFFFF

这给我留下了以下地址:

0x000000000030c486

但是,我正在阅读的文档指出,存储在该地址的数组大小为 4KB,并且自然对齐。

我对自然对齐的实际含义有点困惑。我知道对于页面对齐的东西,地址通常以“000”结尾(尽管我可能错了)。

我假设从起始值获取的地址只有 40 位长,我需要执行额外的位移操作来排列这些位,以便可以进一步正确解释它们。

如果有人可以就此提供一些建议,我将不胜感激。

谢谢

4

4 回答 4

5

通常,“自然对齐”意味着任何项目至少对齐到其自身大小的倍数。例如,一个 4 字节的对象与一个 4 的倍数的地址对齐,一个 8 字节的对象与一个 8 的倍数的地址对齐,等等。

对于数组,您通常不会查看整个数组的大小,而是查看数组元素的大小。

同样,对于structor union,您通常会查看最大元素的大小。

于 2013-03-19T15:34:54.153 回答
2

“自然对齐”地址是处理器上数据类型首选的某个值的倍数。对于大多数常见处理器上的大多数基本数据类型,首选对齐方式与数据大小相同:四字节整数应对齐四字节的倍数,八字节浮点数应对齐八字节的倍数, 等等。有些平台需要对齐,有些只是更喜欢它。某些类型的对齐要求与其尺寸不同。例如,一个 12 字节的long float可能需要四字节对齐。具体值取决于您的目标平台。“自然对齐”不是一个正式术语,因此有些人可能只将其定义为数据大小倍数的首选对齐,而其他人可能允许它用于处理器上首选的其他对齐。

从 64 位值中取出位表明地址已以某种方式进行了转换。例如,地址中的密钥位已存储在页表条目中。重建原始地址可能会也可能不会像提取位并将它们一直移动到“右”(低端)那样简单。然而,像这样的位被移动到不同的位置也是很常见的(在低位留下零)。您应该仔细检查文档。

请注意,4 KiB 数组,4096 字节,对应于 2 12字节。12 与 64 位值中的 51:12 字段的重合表明,可以简单地通过提取这 40 位而不移动它们来获得地址。

于 2013-03-19T15:33:36.117 回答
2

自然对齐要求每个 N 字节访问必须在 N 的内存地址边界上对齐。我们可以用模运算符来表达这一点:addr % N 必须为零。举些例子:

从地址 0x10004 访问 4 个字节的内存是对齐的 (0x10004 % 4 = 0)。

从地址 0x10005 访问 4 个字节的内存是未对齐的 (0x10005 % 4 = 1)。

于 2013-03-19T15:34:29.830 回答
2

从硬件的角度来看,内存通常被分成一定大小的块,这样一个块中的任何或所有数据都可以在单个操作中读取或写入,但任何单个操作只能影响单个块中的数据。

典型的 80386 时代系统会将内存分组为四字节块。访问完全适合单个块的两字节或四字节值将需要一个操作。如果该值部分存储在一个块中,部分存储在另一个块中,则需要两个操作。

多年来,块大小已经变得大于数据大小,以至于大多数随机放置的 32 位值完全适合一个块,但是某些处理器可能会出现第二个问题:如果一个块是例如 512 位( 64 字节),并且已知 32 位字以四个字节(32 位)的倍数对齐,获取字的每个位可以来自 16 个位置中的任何一个。如果不知道单词是否对齐,则对于单词完全适合块的情况,每个位都可能来自 61 个位置中的任何一个。从 61 个选项中快速选择的电路比在 16 个选项中选择的电路更复杂,并且大多数代码将使用对齐的数据,因此即使在一个未对齐的单词适合单个可访问块的情况下,硬件可能仍需要一些额外的是时候提取它了。

于 2016-04-14T18:46:39.693 回答