Setting Individual Bits
Let's talk about controlling devices with a computer.
- Imagine that you have a light or a motor that you need to turn on and off with a computer program.
- On or off can be controlled by a single bit; let's say 1 is on and 0 is off.
- For the moment, let's ignore the question of how the bit gets from the computer to the device.
- That leaves the question of how the program turns the bit on and off.
- Let's start with the easier case: turning a bit on.
- We will exploit the properties of the OR instruction:
- 0 OR 0 = 0; 0 OR 1 = 1; i.e. 0 OR x = x
- In other words, when we OR anything with 0, it doesn't change.
- 1 OR 0 = 1; 1 OR 1 = 1; i.e. 1 OR x = 1
- In other words, when we OR anything with 1, we always get a 1.
- In a program, all of our operations work on 32 bits at a time,
but we will usually change just some of them at any given time:
- For example, suppose we have two lights that we want to control independently.
- We can use the two least-significant bits of a word to do this.
- Let's say that bit 1 controls light A, and bit 0 controls light B.
- We have to have these bits in a register in order to change them.
- Then we have to copy them to another (for now very mysterious) place for the change to take effect.
- Just for convenience, let's say that we keep the other 30 bits in the register as 0's all the time.
- Knowing that, we can just write the two interesting bits
and ignore the others (i.e. 01 instead of 00000000000000000000000000000001.
- Now let's suppose that both lights are off, and we want to turn light B on.
- We would need bit 0 on and bit 1 off in our control register.
- I.e. we want our register to have the value 01 binary; that's 1 in decimal or hex.
- Suppose instead that we wanted to turn on light A.
- We would need bit 1 on and bit 0 off, i.e. a value of 10 binary; i.e. 2 in decimal or hex).
- We can make such changes as this by ORing our register against a mask.
- We can choose the mask so that some bits are turned on and the others are not changed.
- To turn on light A, the mask should be 2: ori $s0 $s0 2
- To turn on light B, the mask should be 1: ori $s0 $s0 1
- To turn on both lights at once, the mask should be 3: ori $s0 $s0 3
- If the mask were to be 0, nothing would change.
- In general, each bit in the mask determines what happens to the
bit in the same position in our control register
- We put 0's where we want the bit to stay as it is,
and we put 1's where we want to be sure that the bit is a 1.
- If we were to turn on a light that was already on, it would just stay on.
- The mask isn't affected by the OR operation;
it just affects what happens to our control register ($s0 in the examples above).
- And don't forget that we still have to copy the register somewhere, but we're ignoring that for now.
- Let's talk a little bit about how we write masks in a program.
- So far, with the really simple masks we have been using, it's easy.
- Now imagine controlling 32 lights with a single register.
- Figuring out what mask we need is a bit more complicated.
- Suppose we need to turn on light X and leave the others as they are.
- We decide that we need to turn on bit 17.
- How can we get the mask from that?
- Using hex makes it a lot easier:
- We need a mask with all bits 0 except that bit 17 is a 1.
- That's pretty easy to write down in binary: 00000000000000100000000000000000.
- Or better this way: 0000-0000-0000-0010-0000-0000-0000-0000
- In hex that's 00020000; in a MIPS program, we'd write it as 0x00020000.
- Now imagine doing this for bits 24, 19 15 11, 7, 5, and 2.
- Not so bad using hex but pretty ugly if you insist on using decimal.
- That's why we'll generally write our masks in hex.