Language: EN

como-usar-mascaras-en-binario

What are and how to use masks and flags in binary

A mask is a binary value that we use to select or modify specific bits within a variable or register.

You can think of masks as if we wanted to draw on a paper, and we placed a cardstock with a cut-out shape to use as a template and not go outside the lines.

curso-binario-mascaras

A mask for spray painting

Masks are commonly used in combination with bit operators to perform bit manipulation operations (such as clearing, setting, or checking bits).

The use of masks is often related to the concepts of flags and registers. You can use masks in other cases, but it is usually when using registers.

What are registers and flags

A register is a binary number that we use to “store several things”. In a register, each bit (or group of bytes) has a specific meaning.

For example, imagine you are communicating data between two machines. Here, you might have a register whose bits represent the state of the communication, such as:

  • Bit 0: Transmission success.
  • Bit 1: Parity error.
  • Bit 2: Data received correctly.
  • Bit 3: Complete packet received.
  • And so on…

These bits are known as Flags, or status indicators. They are specific bits in a register that indicate certain conditions or results after executing an instruction or operation.

This is a convenient way to reduce the amount of memory needed and improve the speed of calculations. But conversely, it forces us to have mechanisms to check only a group of bits.

What are masks

A mask is a sequence of bits, where each bit acts as a selector or “switch” that activates or deactivates the corresponding position in the target data.

Masks are simply a binary number that contains 0 in the positions that interest us, and 1 in the positions that do (or vice versa, depending on the operation we want to perform).

Then we can play with AND and OR to execute actions on a binary number, using this mask to act only on the part that interests us.

Using masks

Getting Bits with masks

The simplest case is to use a mask to read a subset of bits from a register. To do this, we will apply our mask to the register with a AND operation.

  • The values that are 0 in the mask are eliminated
  • The values that are 1 in the mask have the same value as they had in the register.

For example, to extract a field of bits from a variable, we can create a mask with ones in the positions corresponding to the field we want to extract and zeros in the other positions.

variable = 10110110   // 8-bit variable
mask = 00001111       // Mask for the last 4 bits

result = variable & mask  // Extract the last 4 bits

With this, we would obtain 00000110, which are the last 4 bits of the original register.

Bit Manipulation with masks

We can also use masks to modify or query specific bits in a larger bit sequence. For this, we will play again with AND and OR, and the value of the register itself.

Example of setting a bit For example, suppose we have an 8-bit variable and we want to set the third bit to 1 while leaving the other bits unchanged. We can achieve this using a mask and the OR bitwise operator:

variable = 01101001 // 8-bit variable initialized to 00001000
mask = 01101101     // Mask for the third bit

result = variable | mask     // Set the third bit to 1

When performing a OR operation with the value of the variable itself, and the mask

  • If there is a 0 in the mask, the final value will be what it was in the variable
  • If there is a 1 in the mask, the final value will be 1

That is, the OR operator imposes its 1’s.

So with the mask and OR we have set flag 3 of the register to 1, leaving the rest unchanged. Thus, the result would be 01101101.

Example of clearing a bit

Let’s look at the opposite case, now we want to force a 0 in the variable. For this, we will use the AND bitwise operator.

variable = 00011101 // 8-bit variable initialized to 00001000

mask = 11111011      // Mask for the third bit (we invert the bit in position 2)

// Clear the third bit using the mask.
result = variable & mask;

When performing a AND operation with the value of the variable itself, and the mask

  • If there is a 1 in the mask, the final value will be what it was in the variable
  • If there is a 0 in the mask, the final value will be 0

That is, the AND operator imposes its 0’s.

So with the mask and AND we have set bit 3 of the register to 0, leaving the rest unchanged. Thus, the result would be 00011001.

This is fine to explain it, but we had to make the mask “the other way around,” with 0 where we want to act, and 1 where we don’t want to act. There’s nothing wrong with that, but it’s not the usual practice.

Generally, the norm would be to keep the mask “normal,” and invert it before applying it.

variable = 00011101 // 8-bit variable initialized to 00001000
mask =  00000100    // Mask for the third bit 

// Clear the third bit using the mask.
result = variable & ~mask;