Example 2: Hints on Using BitmasksIn building your assembler and your simulator for Project 1 (and later projects as well), you will often need to look at only a portion of an integer -- to pull out a selected group of bits, ignoring all the rest. For instance, if you want a 3-bit field in an instruction that identifies a register number, you will not want the surrounding bits.
This is done using bitmasks, or just masks. A mask is a field of bits that corresponds to the number of bits that you want to pull out of the integer. You shift either the instruction or the mask over to the appropriate place and perform an and to extract the desired bits; I will demonstrate this in a moment.
First, here is a table that you can use; it shows a bit pattern and the corresponding hexadecimal number that you would use to create the mask.
#Bits Bit Pattern Hexadecimal Number 1 1 0x1 2 11 0x3 3 111 0x7 4 1111 0xf 5 11111 0x1f 6 111111 0x3f 7 1111111 0x7f 8 11111111 0xff 9 111111111 0x1ff 10 1111111111 0x3ff 11 11111111111 0x7ff 12 111111111111 0xfff... and so on.
How do you use this? Very simple. If you want to extract a field from an integer called, for instance, "instruction", and place it into the variable "field", you would do the following. Say that you want a three-bit field from bit 12 to bit 14, assuming that the first bit is bit 0.
field = (instruction >> 12) & 0x7;This shifts the bits in "instruction" down by 12 bits, then uses a mask to zero out everything but the bits in the lowest three places (bits 0-2). After the shift, bits 12-14 are in locations 0-2, so this is exactly what we want.
field = (instruction >> 8) & 0xf;
field = (instruction >> 2) & 0x3f;
field = (instruction >> 13) & 0x7;Now, suppose that you want to insert a field into the integer called "instruction". Let's say that you have an opcode value or a register value or something like that held in the variable "field" and you want to put it into the variable "instruction". Say that it is a 3-bit quantity and you want it in bits 10-12.
instruction = (field & 0x7) << 10;The and ensures that "field" contains a 3-bit number (by zeroing out any other bits), and the shift puts the three-bit field into place. The problem is that the variable "instruction" now contains only the three-bit field now in bits 10-12. In the general case, we would like to construct instructions out of many fields. Here is how.
Suppose we have a 3-bit opcode stored in the variable op, we have a 3-bit register stored in the variable r1, and we have another 3-bit register stored in the variable r2. Say we want them (respectively) in bits 15-13, 12-10, and 9-7. We would build up the instruction as follows:
instruction = ((op & 0x7) << 13) | ((r1 & 0x7) << 10) | ((r2 & 0x7) << 7);The ands ensure that each variable is only three bits wide, by masking out all other bits. The left-shifts put the values into place, according to the desired location. Since there is no overlap between the fields (we have ensured this by masking out any possible extra bits), the ors simply concatenate the fields together.
Hope this helps,