Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting bits

In C, I have a 32-bit word representing an address (and I have it stored in an unsigned long, hope that's ok). Now from what I gather, part of an address contains the page number and the other part contains the offset. I was wondering how I could extract just the bits that give me the page number. I have already worked out the first 22 most significant bits are the page number and the other 10 bits are the page offset. How can I grab just the bits that are the page number? I am thinking I can do this with some bitwise operations, but am not sure how.

like image 212
Stephen Avatar asked Nov 29 '09 22:11

Stephen


People also ask

How do I use the extract bits block?

The Extract Bits block allows you to output a contiguous selection of bits from the stored integer value of the input signal. Use the Bits to extract parameter to define the method for selecting the output bits.

How do I extract bits from the input signal?

The Extract Bits block allows you to output a contiguous selection of bits from the stored integer value of the input signal. Use the Bits to extract parameter to define the method for selecting the output bits. Select Upper half to output the half of the input bits that contain the most significant bit.

How to extract the value of a bit in binary?

If you select Upper half for the Bits to extract parameter, the output is 11011 in binary. If you select Lower half for the Bits to extract parameter, the output is 11001 in binary.

How to extract bits from a floating-point input?

Contiguous selection of extracted bits, specified as a scalar, vector, matrix, or N-D array. Floating-point inputs are passed through the block unchanged. Select the method for extracting bits from the input signal. If you select Upper half for the Bits to extract parameter, the output is 11011 in binary.


2 Answers

Use the bitshift operators to extract the bits you need.

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

For the page number, the >> operator shifts bits down, so you lose the least signifcant bits.

For the offset, ((1 << 10) - 1) creates a bitmask consisting of 10 ones which is used to select only the 10 least significant bits and ignore the most significant bits.

like image 81
Mark Byers Avatar answered Nov 11 '22 20:11

Mark Byers


I'm a huge fan of the "two shifts" method of field extraction. It works both signed and unsigned. To extract a field of width w with least significant bit lsb from word:

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

In this case, BITSIN(word) == 32 and lsb+width == 32, so as long as the word in question is unsigned, you can just shift right 10 without masking.

One caution: beware 32-bit shifts on 32-bit types! The C standard lets the compiler do anything, and what the common Intel chips do is not useful: x << y shifts x left by y % 32 bits (provided x has a 32-bit integer type). This means if you try to shift a 32-bit integer left or right by 32 bits, the result is the same as a no-op. There is a similar issue with 64-bit shifts of 64-bit types.

like image 45
Norman Ramsey Avatar answered Nov 11 '22 22:11

Norman Ramsey