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.

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

You can think of masks as if you wanted to draw on paper, and you put a piece of cardboard with a cut-out shape to use as a template and not go outside.

curso-binario-mascaras

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

What are registers and flags

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

For example, imagine that you are data communicating 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 correctly received.
  • Bit 3: Complete packet received.
  • And so on…

These bits are known as Flags, or state 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 required and improve the speed of calculations. But, on the other hand, 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 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 perform actions on a binary number, using this mask to act only on the part that interests us.

Use of masks

Obtain bits with masks

The simplest case is to use 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 as in the register.

For example, to extract a bit field 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 get 00000110, which are the last 4 bits of the original register.

Bit manipulation with masks

We can also use masks to modify or check 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 keeping 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

By performing an OR operation of the value of the variable itself, with the mask

  • If the mask has a 0, the final value will be the same as 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 1 to the 3rd flag of the register, leaving the rest unchanged. So 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 that, we are going to 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)

// Clean the third bit using the mask
result = variable & mask;

By performing an AND operation of the value of the variable itself, with the mask

  • If the mask has a 1, the final value will be the same as 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 0 to the 3rd bit of the register, leaving the rest unchanged. So the result would be 00011001.

This is fine to explain 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, it would be normal 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 

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