Bitmasking

Author

Clayton Cafiero and Surya Malik

Published

2026-10-01

Important

Code examples and bitwise operators presented here use Python conventions. Other programming languages may use different symbols for some or all bitwise operations.

 

Bitmasking

Bitmasking is a powerful technique for manipulating binary data. It lets us select, modify, or test specific bits.

Understanding bitwise operations

Before we can work with bitmasks, we need to understand how to manipulate data at the bit level. This is done using bitwise operations and bit shift operations, which act directly on individual bits of some value.

Bitwise operations are the building blocks for masking, shifting, and setting flags in hardware and low-level software. They mirror the logic of real electronic circuits that use AND, OR, XOR, and NOT gates to process binary signals.

What bitwise operations do

A bitwise operation compares or modifies individual bits in a binary value. Each bit or pair of bits is processed separately, without affecting the others. This is very different from normal arithmetic, which treats the entire number as one value.

For example, consider these two binary numbers: 0b1100 and 0b1010. A bitwise operation applies a logical rule to each pair of bits. The result is another binary number of the same length.

operation description example result
AND (&) Keeps only the bits that are 1 in both operands 0b1100 & 0b1010 0b1000
OR (│) Sets bits to 1 if they are 1 in either operand 0b1100 │ 0b1010 0b1110
XOR (^) Sets bits to 1 if they are different in each operand 0b1100 ^ 0b1010 0b0110
NOT (~) Flips (inverts) every bit (1 becomes 0, 0 becomes 1) ~0b1100 0b0011

 

These are the same logical operations that are physically implemented by transistor-based gates inside a CPU.

Bitwise AND

The bitwise AND operation, when used for bitmasking, is like a bit-level filter. It only keeps the bits that are set to 1 in both operands. If either bit is 0, the result will be 0.

Python uses & for bitwise AND.

>>> a = 0b1100  
>>> b = 0b1010  
>>> bin(a & b)
'0b1000'

In other words, AND can be used to “mask out” bits we do not want. When we use it with a specific mask value, the 1 bits in the mask act like windows that let data through, and the 0 bits block.

Note

Think of bitwise AND as a selective pass filter. It lets through bits wherever the mask has a 1 and blocks everything else.

Here’s another example: Say we wanted to isolate the upper nibble of a byte. First, let’s write a little function so we can display results in binary with a specific width guaranteed (Python will remove leading zeros and we want to keep them).

>>> def binw(n, width):
...     # remove leading 0b, pad with zeros, add 0b back and return
...     return f"0b{bin(n)[2:].zfill(width)}"
...
>>> binw(0b00000001, 8)
'0b00000001'

So that checks out. Now, on to our example.

>>> a = 0b01011101  
>>> b = 0b11110000   # mask will let bits of the upper nibble through
>>> binw(a & b, 8)
'0b01010000'

Now let’s filter out all but the lower nibble.

>>> a = 0b01011101  
>>> b = 0b00001111   # mask will let bits of the lower nibble through
>>> binw(a & b, 8)
'0b00001101'

Bitwise OR

The bitwise OR operation “combines” bits. If either of the bits in a given position is 1, the result will also be 1. This is useful for setting specific bits to 1 while leaving others unchanged.

Python uses | for bitwise OR.

>>> a = 0b1100  
>>> b = 0b1010  
>>> binw(a | b, 4)
'0b1110'

If you have a register and you want to turn on one or more bits without changing the others, you can apply bitwise OR with a mask that has 1s in the desired positions. For example: If a bit controls an LED or a CPU flag, bitwise OR with a mask will “turn on” that flag without disturbing other bits.

>>> a = 0b10001100  
>>> b = 0b00100000  # to set this one bit in `a`, leaving other bits unchanged
>>> binw(a | b, 0)
'0b10101100'

Notice that only one bit in a was changed.

Bitwise XOR

Bitwise XOR (exclusive OR) compares each bit in two operands, and sets bits 1 only when the two bits in the operands are different.

Python uses ^ for bitwise XOR.

>>> a = 0b1100  
>>> b = 0b1010  
>>> binw(a ^ b, 4)
'0b0110'

Bitwise XOR is often used to “toggle” bits or detect differences between two patterns. If you XOR a bit with 1, it flips. If you XOR it with 0, it stays the same.

>>> 1 ^ 1
0
>>> 0 ^ 1
1
>>> 1 ^ 0
1
>>> 0 ^ 0
0

This property makes XOR useful in checksum generation, encryption, and control logic.

Bitwise NOT

Bitwise NOT operation (also called bitwise complement) flips all the bits in an operand. Every 1 becomes a 0, and every 0 becomes a 1.

Python uses ~ for bitwise NOT.

>>> a = 0b1100
>>> binw(~a, 4)
0b0011

In two’s complement for signed integers, the NOT operation is closely related to negation. However, when masking, we mostly use it to invert a mask. This allows us to clear bits rather than set them.

Note

If a mask has 1s in the bits we want to keep, then ~mask will have 1s in the bits we want to remove. This pattern is used for clearing selected bits.

Shifting bits

In addition to bitwise logical operations, we can shift bits left or right within an operand. These operations are called “bit shifts.”

Python uses << for left shift and >> for right shift.

operation symbol description example result
left shift << moves bits to the left by n positions 0001 << 3 1000
right shift >> moves bits to the right by n positions 1000 >> 3 0001

 

(Note: left shifts multiply an integer by powers of two, while right shifts divide by powers of two.)

We can use bitshift to build bitmasks dynamically. For example, 1 << 7 creates a mask with only bit 7 set.

>>> binw(1 << 0, 8)
'0b00000001'
>>> binw(1 << 1, 8)
'0b00000010'
>>> binw(1 << 7, 8)
'0b10000000'
Tip

Shifting is one of the most common operations used in masking. It lets you place a single 1 bit exactly where you need it without having to count manually.

Bitwise Operations in ARM Assembly

Bitwise logic operations are directly supported in the ARM instruction set. These are often used to manipulate bits inside registers.

ARM instruction meaning use
ANDS Rd, Rn, Rm bitwise AND, sets condition flags mask selected bits
ORR Rd, Rn, Rm bitwise OR combine or set bits
EOR Rd, Rn, Rm bitwise XOR toggle bits
BIC Rd, Rn, Rm bit Clear (Rn & ~Rm) clear specific bits

 

For example:

MOV R1, #0xFF00  
AND R2, R0, R1   ; Clear the lower 8 bits of R0

This instruction uses AND to keep only the upper byte of the register, which is a simple form of bitmasking.

© 2025 Clayton Cafiero.

No generative AI was used in writing this material. This was written the old-fashioned way.