我需要从现有的64位值中提取内存地址,此地址指向4K数组,起始值为:
0x000000030c486000
我需要的地址存储在51:12位,所以我使用以下方法提取这些位:
address = start >> 12 & 0x0000007FFFFFFFFF
这给我的地址是:
0x000000000030c486
但是,我正在阅读的文档说明存储在该地址的数组大小为4KB,并且自然对齐。
我对自然对齐实际意味着什么有点困惑。我知道页面对齐的东西,地址通常以'000'结尾(虽然我可能错了)。
我假设由于从起始值获取的地址只有40位长,我需要执行额外的位移操作来排列这些位,以便可以进一步正确解释它们。
如果有人能就这样做提出一些建议,我会很感激。
由于
答案 0 :(得分:3)
通常,“自然对齐”意味着任何项目至少与其自身大小的倍数对齐。例如,一个4字节的对象与一个4的倍数对齐,8字节的对象与8的倍数对齐,等等。
对于数组,通常不会查看整个数组的大小,而是查看数组元素的大小。
同样,对于struct
或union
,您通常会查看最大元素的大小。
答案 1 :(得分:2)
“自然对齐”地址是对于处理器上的数据类型优选的某个值的倍数的地址。对于大多数常见处理器上的大多数基本数据类型,首选对齐方式与数据大小相同:四字节整数应在四个字节的倍数上对齐,八字节浮点应在八个字节的倍数上对齐, 等等。有些平台需要对齐,有些只是喜欢它。某些类型的对齐要求与其大小不同。例如,10字节long float
可能需要四字节对齐。具体值取决于您的目标平台。 “自然对齐”不是一个正式术语,因此有些人可能只将其定义为数据大小的倍数的首选对齐,而其他人可能允许将其用于处理器上首选的其他对齐。
从64位值中取出位表明地址已经以某种方式转换。例如,来自地址的密钥位已存储在页表条目中。重建原始地址可能会也可能不会像提取位并将它们一直移到“右”(低端)一样简单。然而,诸如此类的比特也常常被移位到不同的位置(在低比特中保留零)。您应该仔细检查文档。
注意,4 KiB阵列(4096字节)对应于2 12 字节。 12与64位值中51:12字段的重合表明,只需提取这40位而不移动它们就可以获得地址。
答案 2 :(得分:2)
自然对齐要求每个N字节访问必须在N的存储器地址边界上对齐。我们可以用模数运算符表示:addr%N必须为零。例如:
从地址0x10004访问4个字节的内存是对齐的(0x10004%4 = 0)。
从地址0x10005访问4个字节的内存是未对齐的(0x10005%4 = 1)。
答案 3 :(得分:1)
从硬件角度来看,内存通常被划分为某种大小的块,这样块中的任何或所有数据都可以在单个操作中读取或写入,但任何单个操作只能影响单个数据块。
典型的80386时代系统将内存分为四个字节的块。访问完全适合单个块的两字节或四字节值将需要一个操作。如果值部分存储在一个块中而部分存储在另一个块中,则需要进行两次操作。
多年来,块大小已经大于数据大小,以至于大多数随机放置的32位值完全适合于块,但是某些处理器可能出现第二个问题:如果块是例如块。已知512位(64字节)和32位字以四个字节(32位)的倍数对齐,取出该字的每个位可以来自16个位置中的任何一个。如果不知道该单词是否对齐,则对于单词完全适合该块的情况,每个位可以来自61个位置中的任何一个。从61个选项中快速选择的电路比在16个中选择的电路更复杂,并且大多数代码将使用对齐的数据,因此即使在未对齐的字适合单个可访问的块的情况下,硬件可能仍需要一些额外的提取它的时间。