Bitmask Generator & Register Workbench
Build, paste and visualize bitmasks at 8, 16, 32 or 64 bits - then generate the set, clear, toggle and field-extract code for them.
Click a bit to add or remove it from the mask · MSB (bit 31) left → LSB (bit 0) right
0x000000F02400o3600xFFFFFF0F0000 0000 0000 0000 0000 0000 1111 0000- Bits set
- 4
- Ranges
- [7:4]
- Shift (LSB)
- 4
- Field capacity
- 4-bit, max 15
Presets
Masks lifted straight from datasheets and runtimes - load one, then adjust the bits.
Emitted as FIELD_MASK
Code for this mask
Regenerated from the mask above on every change - never a canned 0xF0 example.
/* 32-bit mask over bits [7:4] */
#define FIELD_MASK 0x000000F0u
#define FIELD_SHIFT 4u
uint32_t reg = 0;
reg |= FIELD_MASK; /* set */
reg &= ~FIELD_MASK; /* clear */
reg ^= FIELD_MASK; /* toggle */
/* read the field, right-aligned */
uint32_t value = (reg & FIELD_MASK) >> FIELD_SHIFT;
/* write the field without disturbing the other bits */
reg = (reg & ~FIELD_MASK) | ((value << FIELD_SHIFT) & FIELD_MASK);Practical examples
Configuring an STM32 GPIO pin
GPIOx_MODER packs two bits per pin, so pin n lives at bits [2n+1 : 2n]. For pin 5 that is [11:10], mask 0x00000C00, shift 10. You cannot just OR the mode in: the field already holds the reset value, so it has to be cleared first. That is exactly the read-modify-write the Write field operation generates - MODER = (MODER & ~0xC00) | (0x1 << 10) puts the pin in general-purpose output mode without disturbing the other fifteen pins.
Enabling an AVR USART
UCSR0B holds RXEN0 at bit 4 and TXEN0 at bit 3. Enabling both is a single set: UCSR0B |= (1 << RXEN0) | (1 << TXEN0), which is mask 0x18. Because it is an OR, the interrupt-enable bits already in the register survive - the reason firmware never writes a whole register with = unless it means to reset every field in it.
Building a DPDK or taskset core mask
Core affinity masks are one bit per logical CPU, so cores 0-3 are 0xF and cores 8-11 are 0xF00. Set the register width to 64 and click the cores you want - a 96-core box needs two masks, because the bit index is the core number and nothing above 63 fits in a single 64-bit word.
Unpacking a packed colour or flags word
A 0x00RRGGBB pixel is three 8-bit fields: red is 0x00FF0000 shift 16, green 0x0000FF00 shift 8, blue 0x000000FF shift 0. Describe it once in the Struct layout tab (blue, green, red, alpha at 8 bits each) and the generated accessors do the shifting for you.
How bitmasks work
A bitmask is an integer used as a stencil. Every position that is 1 in the mask selects a bit in the target value; every 0 leaves the corresponding bit alone. That one idea gives you four operations, and firmware, kernels, protocol parsers and permission systems are built almost entirely out of them.
- Set with
reg |= mask. OR can only turn bits on, so unmasked bits are untouched. - Clear with
reg &= ~mask. The inversion is the important half: AND against a mask of mostly ones keeps everything except the selected bits. - Toggle with
reg ^= mask. XOR flips exactly the masked bits, which is how you blink an LED without reading the port back first. - Read with
(reg & mask) >> shift. Masking isolates the field; the shift right-aligns it so you get 3 rather than 0x300.
Writing a multi-bit field is the composite of clear and set: reg = (reg & ~mask) | ((value << shift) & mask). The trailing & mask is not decoration - it stops an oversized value from spilling into the neighbouring field, which is the single most common bit-field bug.
Language gotchas
JavaScript truncates to 32 bits
&, |, ^ and << coerce their operands to signed 32-bit integers, so 1 << 31 is negative and 1 << 32 is 1. Use BigInt literals for anything wider - this page does, which is why the 64-bit masks above stay exact.
Python integers are unbounded
~0xF0 is -241, not 0xFFFFFF0F. Always AND the inverted mask back down to the register width: reg &= ~MASK & 0xFFFFFFFF.
C promotes to int
1 << 31 on a 32-bit int is undefined behaviour, and ~mask on a uint8_t promotes to int first. Write 1u << 31, 1ULL << 40, and keep register variables in explicit uintN_t types.
Rust panics on overflowing shifts
Shifting a u32 by 32 or more panics in debug and is masked to shift % 32 in release. Use checked_shl or wrapping_shl when the amount is not a constant.
Mask reference
Right-aligned masks of every common field width, the values you reach for when a datasheet says “n-bit field”.
| Bits | Range | Hex (32-bit) | Decimal | Max field value |
|---|---|---|---|---|
| 1 | [0:0] | 0x00000001 | 1 | 1 |
| 2 | [1:0] | 0x00000003 | 3 | 3 |
| 3 | [2:0] | 0x00000007 | 7 | 7 |
| 4 | [3:0] | 0x0000000F | 15 | 15 |
| 5 | [4:0] | 0x0000001F | 31 | 31 |
| 6 | [5:0] | 0x0000003F | 63 | 63 |
| 7 | [6:0] | 0x0000007F | 127 | 127 |
| 8 | [7:0] | 0x000000FF | 255 | 255 |
| 12 | [11:0] | 0x00000FFF | 4095 | 4095 |
| 16 | [15:0] | 0x0000FFFF | 65535 | 65535 |
| 24 | [23:0] | 0x00FFFFFF | 16777215 | 16777215 |
| 32 | [31:0] | 0xFFFFFFFF | 4294967295 | 4294967295 |
Frequently Asked Questions
What is a bitmask?
A bitmask is an integer used as a stencil. Every bit that is 1 in the mask selects the matching bit in a target value, and every 0 leaves that bit alone. Masks are how firmware, kernels, protocol parsers and permission systems address individual bits inside a word.
How do I create a bitmask for a range of bits?
For an N-bit field starting at position P the mask is ((1 << N) - 1) << P. A 4-bit field at position 4 gives ((1 << 4) - 1) << 4 = 0xF0. Use the start-bit and length inputs above and the tool computes it, along with the shift you need to right-align the field.
How do I convert a number like 15 to a bitmask?
Paste it into the mask value box - 15, 0xF and 0b1111 all describe the same mask, bits [3:0]. The bit grid lights up the bits that value covers, and the readouts give you the hex, decimal, octal and binary forms plus the inverted mask.
Can I paste an existing hex mask and see which bits it targets?
Yes. Paste 0x02, 0xFF00, 0b1010 or a plain decimal into the mask value field and the grid highlights exactly the bits that mask covers, with the ranges printed in datasheet notation such as [15:8].
How do I set, clear or toggle bits with a mask?
Set with reg |= mask (OR can only turn bits on), clear with reg &= ~mask (AND against the inverted mask), and toggle with reg ^= mask (XOR flips exactly the masked bits). The Register operations tab applies each one to a value you supply and shows the before and after bit patterns with the changed bits highlighted.
How do I read a multi-bit field out of a register?
Mask it, then shift it right by the position of the mask's lowest set bit: value = (reg & mask) >> shift. Without the shift you get the field still sitting in place, so a 3 in bits [9:8] reads as 0x300 rather than 3.
How do I write a field without disturbing the other bits?
Clear then set in one expression: reg = (reg & ~mask) | ((value << shift) & mask). The trailing & mask matters - it stops an oversized value spilling into the neighbouring field, which is the most common bit-field bug.
Does this support 64-bit masks?
Yes, at 8, 16, 32 and 64 bits. Every value is computed with BigInt, so 64-bit masks are exact. That matters because JavaScript's own bitwise operators coerce to signed 32-bit integers, which silently breaks any hand-rolled 64-bit mask in the browser console.
What is a core mask or lcore mask?
A CPU affinity mask: one bit per logical core, so cores 0-3 are 0xF and cores 8-11 are 0xF00. DPDK's -c coremask, taskset and sched_setaffinity all take this form. Switch to 64-bit and click the cores you want.
Why is ~mask wrong in Python?
Python integers are unbounded, so ~0xF0 is -241 rather than 0xFFFFFF0F. You have to AND the inverted mask back down to the register width: reg &= ~MASK & 0xFFFFFFFF. The generated Python above already does this.
Can it generate C bit-field structs?
Yes. The Struct layout tab takes named fields with widths, packs them from bit 0 upwards, and emits the mask and shift #defines plus a union of the raw word and a C bit-field struct, along with Rust and Python equivalents. Prefer the macros for real hardware: C bit-field ordering is implementation-defined.
What happens with a non-contiguous mask?
Set, clear and toggle still work exactly - they are per-bit operations. But a single shift cannot right-align a field split across two runs of bits, so the tool flags the mask as non-contiguous and lists each run separately.
Related Tools
Bitwise Calculator
Perform bitwise operations: AND, OR, XOR, NOT, NAND, NOR - or evaluate full expressions like 0xFF & 0b1010 << 2.
Bit Shift Calculator
Calculate left and right bit shifts with visual representation.
Two's Complement Calculator
Calculate two's complement representation for signed integers.
This tool runs entirely in your browser - nothing you enter is uploaded or stored.