What is bitwise OR used here for?

240 views Asked by At
descriptor  =  limit       & 0x000F0000;        
descriptor |= (flag <<  8) & 0x00F0FF00;        
descriptor |= (base >> 16) & 0x000000FF;        
descriptor |=  base        & 0xFF000000;        

I understood the fact that the and operation is used for masking certain bits. But what is OR operation used here for??? Please elaborate.
This is part of the code for creating a Global Descriptor Table.

5

There are 5 answers

0
amnn On BEST ANSWER

What the code you've shown is doing is constructing descriptor by selecting different parts of it from other boolean expressions.

Notice that the constants that (flag << 8), (base >> 16) and base are being ANDed with, when themselves ORed together, produce 0xFFFFFFFF.

The point of the OR is to say, "the first 8 bits come from (base >> 16), the next 8 bits from flag << 8, the next 4 from limit, the next 4 from flag << 8 and the last 8 from base." So finally, descriptor looks like this:

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

Where each comma separated variable is a hexadecimal digit, and a, b, c, and d are limit, (flag << 8), (base >> 16) and base respectively. (The commas are just there for readability, they stand for concatenation of the digits).

1
JaredPar On

The use of |= here is essentially short hand for the following

descriptor = destriptor | ((flag <<  8) & 0x00F0FF00);
10
David Heffernan On

If you look at just a single bit, the truth table is given by

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

So, bitwise or sets a bit if and only if that bit is set in at least one of the operands.


When you use bitwise or on a variable with more that a single bit, the above truth table is applied in a bitwise fashion.

So, suppose that you had two variables whose binary representations were

001101
011001

When you combine them with bitwise or, you collect all the bits that are set in either variable. So the result is

011101

The bitwise or operator is commonly used to add new flags to a set of bit flags. The value is used to represent a mathematical set. Each bit is assigned a particular meaning, that is associated with a member of the universal set. When the bit is 1, that member is included in the set, and when the bit is 0, the associated member is not in the set.

So, let us have a very simple example with a universal set having two members. Let us call the variable, controlState. Bit 0 represents the visible property, and bit 1 represents the enabled property. So, you can define flags like so

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

Then you can build the controlState variable like this:

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

It gets more interesting if you don't know whether or not a particular bit is set. So, you can ensure that the visible bit is set like this:

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

It does not matter whether the original value of controlState included the flag or not. After this operation, it will be set for sure, and no other flags altered.


This is what is happening in your code example. So,

descriptor  =  limit       & 0x000F0000;        

initializes descriptor. Then

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

adds (flag << 8) & 0x00F0FF00. And so on.

0
haccks On

Bit-wise OR | operator (copies a bit if it exists in either operand) used here to ORing the descriptor with right hand operator of = and store the result to descriptor. It is equivalent to

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

Truth table fo OR operation:

enter image description here

For x = 1 1 0 0 and Y = 1 0 1 0 OR operation works as follows:

enter image description here

0
Dithermaster On

descriptor is a collection of values packed together as bitfields. This code is building it up from four values (limit, flag, and two parts of base). Each step is shifting the value to the correction bit position and then ANDing with a mask to ensure the bits don't spill over into other positions. The A |= B operator expands to A = A | B and merges together all of the individual results. This could also be done using a struct with bitfields, although perhaps with less portability.