Wrapping your head around the use of bitwise operators can be daunting in the beginning. In my next few posts, I’m going to attempt to walk through some common use cases for bitwise operators that I’ve encountered.
The first use case I’m going to discuss is protocol decoding. Data is stored in bytes, each of which is comprised of eight bits, with a total of 256 possible values per byte (0 to 255). Many common protocols, especially long-lived ones like IPv4, pack multiple values into a single byte to save space. Here’s an example.
Several of the values here do not line up directly on octet (byte) boundaries. From this chart, how would we get the version, which takes up only the first half of the first byte? To begin, we need to get the whole byte. A common value here would be
69 in decimal representation. Let’s take a look at what that actually looks like in binary.
A bitwise right-shift simply moves all the bits in a value one position to the right, dropping the rightmost bit and filling the leftmost bit with zero each time the values are moved.
To obtain our value, we will shift those top four bits to the bottom four bits of the byte by doing a right shift (
>>). It will fill in the previous four bits with zeroes.
Let’s take a look at the bit pattern.
This is an IPv4 header, so
4 is the correct value.
AND takes two operands and returns a value with only the bits set to 1 that were set to 1 in both operands. If either operand has a zero for a bit in a position, it will be zero in that position in the result.
Let’s try to get the IHL number. We start back with
We then mask the bits we care about.
This is equal to the decimal number
15. Next, we do our AND operation.
Since the bits were already in the correct position, we didn’t need to perform any shifts. The default value of the IHL field in an IPv4 header is
5, so we’ve got the correct answer! Let’s look at the bit pattern.
AND with Flags
It’s common to see single bits in a byte used as flags. TCP is a good example.
In the 13th octet, you will see that all eight bits are used for individual flags. Let’s say that the
ACK flags are set.
The easiest way to deal with this is an
AND. Let’s take a look at the
ACK flags. The
ACK flag is in the second position. Let’s mask it off.
To check for the individual flag, we simply use an
AND, and then confirm that the result is equal to the value of the mask.
We can also use this technique to check for multiple bits at once. Let’s make a mask to check for three bits being set.
Since the result was
18 but our mask was
19, not all three flags were set.
Combining Right-Shift with AND
Sometimes you’ll want to get a multi-bit value that’s in the middle of a byte. We can combine these two operators to get the data we want, and what’s more, we can do them in any order. Let’s take a look at octet 12 of the TCP header. What if we want to take a look and see if there’s data in the
reserved section? We’ll need to mask those bits and then shift them to the right (or shift them to the right and mask them second). Here’s some random data.
Let’s do a shift first and see what happens.
And here’s the bit pattern
Now we’ll mask the last three bits
And we’ll do an
Which has the bit pattern of
Let’s try in the other order.
We start with our original value.
Now we mask the three bits we want
We perform our
Which has a bit pattern of
Which we then shift right one place
Which gives us the same bit pattern of