提取位

5

在C语言中,我有一个32位的字表示一个地址(并且我已经将其存储在一个无符号长整型变量中,希望这没问题)。现在据我所知,地址的一部分包含页面号,另一部分包含偏移量。我想知道如何提取只给我页面号的位。我已经确定了前22个最重要的位是页面号,其他10个位是页面偏移量。我该如何获取仅为页面号的位?我认为我可以通过一些按位操作来实现,但不确定怎么做。


好问题 - 我也需要为我正在编写的反汇编器做这个。 - new123456
2个回答

11

使用位移运算符提取所需的位。

pageNumber = x >> 10;
offset = x & ((1 << 10) - 1);

对于页码,>> 运算符将位向下移动,因此您会丢失最低有效位。

对于偏移量,((1 << 10) - 1) 创建一个掩码,其中包含 10 个二进制的1,用于仅选择最低的 10 位并忽略最高位。


1
在像这样的代码中,掩盖移位后的位可能是一个好主意,以防您的硬件执行算术(符号扩展)右移。pagenumber = (x >> 10) & ((1 << 22) - 1); - John R. Strohm

2

我非常喜欢“两个移位”的字段提取方法。它适用于有符号和无符号的数据类型。要从word中提取宽度为w,最低有效位为lsb的字段:

#define BITSIN(W) (8*sizeof(W))
return (word << (BITSIN(word) - (lsb+width))) >> (BITSIN(word) - width);

在此情况下,BITSIN(word) == 32lsb+width == 32,因此只要所讨论的字是无符号的,你可以直接向右移10位而不需要进行掩码操作。
请注意:谨防对32位类型进行32位移位操作!C标准允许编译器执行任何操作,而常用的英特尔芯片做法并不实用:x << yx左移y % 32个比特(前提是x具有32位整数类型)。这意味着如果你尝试将一个32位整数左移或右移32位,结果就像没有操作一样。64位类型的64位移位也存在类似问题。

"常见的英特尔芯片所做的并不实用" - 那它们做什么呢? - AShelly
@ASHelly:好问题;我编辑了答案。谁知道呢,也许会得到一个赞 :-) - Norman Ramsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接