0
descriptor  =  limit       & 0x000F0000;        
descriptor |= (flag <<  8) & 0x00F0FF00;        
descriptor |= (base >> 16) & 0x000000FF;        
descriptor |=  base        & 0xFF000000;        

我理解 and 操作用于屏蔽某些位的事实。但是这里使用的 OR 操作是做什么用的???请详细说明。
这是创建全局描述符表的代码的一部分。

4

5 回答 5

3

如果你只看一点,真值表由下式给出

0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1

因此,当且仅当在至少一个操作数中设置该位时,按位或设置一个位。


当您按位使用或在具有多于一位的变量上使用时,上述真值表将以按位方式应用。

所以,假设你有两个变量,它们的二进制表示是

001101
011001

当您将它们与按位或组合时,您将收集在一变量中设置的所有位。所以结果是

011101

按位或运算符通常用于向一组位标志添加新标志。该值用于表示数学集。每个位都被分配了一个特定的含义,它与通用集的一个成员相关联。当位为 1 时,该成员包含在集合中,而当位为 0 时,关联的成员不在集合中。

所以,让我们举一个非常简单的例子,一个有两个成员的全集。让我们称变量为controlState。位 0 表示可见属性,位 1 表示启用属性。所以,你可以像这样定义标志

const int visibleFlag = 1; // 01 in binary
const int enabledFlag = 2; // 10 in binary

然后你可以像这样构建controlState变量:

int controlState = 0; // empty set
if (isVisible) 
    controlState |= visibleFlag;
if (isEnabled)
    controlState |= enabledFlag;

如果您不知道是否设置了特定位,它会变得更有趣。因此,您可以确保可见位设置如下:

controlState = ...; // could set visible flag, or not ...
controlState |= visibleFlag;

controlState是否包含标志的原始值无关紧要。在此操作之后,它将被确定设置,并且不会更改其他标志。


这就是您的代码示例中发生的事情。所以,

descriptor  =  limit       & 0x000F0000;        

初始化descriptor. 然后

descriptor |= (flag <<  8) & 0x00F0FF00;

补充道(flag << 8) & 0x00F0FF00。等等。

于 2014-01-04T15:12:25.357 回答
2

您显示的代码正在做的是descriptor通过从其他布尔表达式中选择不同部分来构建。

请注意,与 和 进行与运算的常数(flag << 8)(base >> 16)base它们自身或运算在一起时,会产生0xFFFFFFFF

OR 的意义在于,“前 8 位来自(base >> 16),接下来的 8 位来自flag << 8,接下来的 4 来自limit,接下来的 4 来自flag << 8,最后 8 来自base。” 所以最后,描述符看起来像这样:

d[7], d[6], b[5], a[4], b[3], b[2], c[1], c[0]

其中每个逗号分隔的变量是一个十六进制数字,而a, b, c,和分别dlimit, (flag << 8),和。(逗号只是为了便于阅读,它们代表数字的连接)。(base >> 16)base

于 2014-01-04T15:22:02.867 回答
1

这里的使用|=基本上是以下的简写

descriptor = destriptor | ((flag <<  8) & 0x00F0FF00);
于 2014-01-04T15:11:39.747 回答
0

按位或|运算符(如果存在于任一操作数中,则复制一点)此处用于descriptor与右手运算符进行OR 运算=并将结果存储到descriptor. 它相当于

descriptor = descriptor | (flag <<  8) & 0x00F0FF00;  

OR运算的真值表:

在此处输入图像描述

Forx = 1 1 0 0Y = 1 0 1 0OR 操作的工作原理如下:

在此处输入图像描述

于 2014-01-04T15:14:40.527 回答
0

descriptor是作为位域打包在一起的值的集合。这段代码是从四个值(limitflag和 的两个部分base)构建的。每一步都将值转移到校正位位置,然后使用掩码进行与运算,以确保位不会溢出到其他位置。A |= B运算符扩展A = A | B并合并所有单独的结果。这也可以使用struct带有位域的 a 来完成,尽管可移植性可能较差。

于 2014-01-04T15:16:36.327 回答