como-usar-mascaras-en-binario

What are and how to use masks and flags in binary

  • 5 min

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 piece of paper, and we put a cardboard with a cut-out shape to use as a template so we don’t go outside the lines.

curso-binario-mascaras

A mask for spray painting

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

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

What are Registers and Flags

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

For example, imagine you have a data communication between two machines. Here, you could have a register whose bits represent the status of the communication, such as:

  • Bit 0: Transmission success.
  • Bit 1: Parity error.
  • Bit 2: Data received correctly.
  • Bit 3: Packet received complete.
  • 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 an operation.

This is a convenient way to reduce the amount of memory needed and improve calculation speed. But, on the other hand, it forces us to have mechanisms to check only a group of the 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 0s in the positions we are interested in, and 1s in the positions we are not (or vice versa, depending on the operation we want to perform).

Then we can play with AND and OR to perform 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 using a mask to read a subset of bits from a register. To do this, we are going to apply our mask to the register with an AND operation.

  • Values that are 0 in the mask are removed.
  • Values that are 1 in the mask have the same value 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
Copied!

With this, we would get 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 again play 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 keeping the other bits unchanged. We can achieve this using a mask and the bitwise OR 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
Copied!

By performing an OR operation of the variable’s own value with the mask:

  • If the mask has a 0, the final value will be what it was in the variable.
  • If the mask has a 1, 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. So the result would be 01101101.

Example of clearing a bit

Let’s see the opposite case, now we want to force a 0 in the variable. For that we are going to use the bitwise AND 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;
Copied!

By performing an AND operation of the variable’s own value with the mask:

  • If the mask has a 1, the final value will be what it was in the variable.
  • If the mask has a 0, 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. So the result would be 00011001.

This is fine for explaining it, but we had to make the mask “backwards”, 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 way.

In general, the normal thing would be to leave 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;
Copied!