Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

What are the 8 bits in 8-bit computing?

Jerry Stratton, April 7, 2021

AND and OR on the Color Computer: AND and OR in Extended Color BASIC on the TRS-80 Color Computer.; 8-bit bytes; computer logic

Why? Where do these results come from?

On the Facebook CoCo group, someone recently asked about how I handled bit-checking in a question I asked on the Retrocomputing StackExchange about the joystick. They didn’t phrase it as a question about bits because they didn’t know that their question was about bits.

It’s not surprising. I don’t know about other computers, but Radio Shack tended to hide the bitwise nature of their 8-bit computers. The only BASIC functions that worked with bits were the logical operators AND, OR, and NOT1, and they weren’t explained as bitwise. The first two are given a page in Getting Started with Extended Color BASIC, page 78, where they’re explained as if they’re the English words AND and OR.2

But these operators do not behave as the English words do, or as the explanation implies they do. Here’s an example. Go into your CoCo or an emulator such as Xroar, and type:

  • PRINT 3 AND 5
  • PRINT 3 OR 5

The first should give you 1 and the second should give you 7. In most modern programming languages, both would give you true, which, depending on the language, might be a boolean value or it might be the integer 1. It might even be one of the two values, the 3 or the 5, because of short-circuit evaluation.

How does Extended Color BASIC arrive by its return values? The answer is that AND and OR are bitwise operations. These are 8-bit computers. They describe their numbers in 8 bits3. Here are the bits for the numbers 3 and 5:

byte value8 bits

The logical operators do not compare bytes. They compare individual bits at matching bit locations. What AND does is, if the bit in the same location in each byte is 1, the bit in the resulting byte is 1. If either of the two bits are zero, the bit in the result for that location is zero. What OR does is return 1 if either of the bits are 1, and zero only if both bits are zero. So here’s what AND and OR do when comparing 3 and 5:

logic examplelogic resultexplanation
3 AND 500000001Only the 1st bit (counting from the right) is 1 in both cases, so it’s the only 1 in the result.
3 OR 500000111The 1st, 2nd, and 3rd bits all have a 1 in one of the numbers, so all three of them are 1 in the result.

So, why does 3 AND 5 return 1 in the example? Because the rightmost bit (bit number 1) is a stand-in for 1.

Why does 3 OR 5 return 7 in the example? Because bit 1 is a stand-in for 1, bit 2 is a stand-in for 2, and bit 3 is a stand-in for 4. Add them all together and you get 7.

Each bit, counting from the right, stands for a power of two. The rightmost bit is 2^0; the second rightmost bit is 2^1; the third is 2^2, and so on.4

Bit (from right)Power of twoValueBit location

This is sometimes called “binary notation”, sometimes “base 2”.5 To get the value of a byte in an 8-bit computer, you add up the powers of two for all of the bits that are set to 1, and you end up with a number from zero to 255.

All numbers from 0 to 255 can be represented as the sum of powers of two. The value for 75, to pull a number out of the random dice roller from 42 Astounding Scripts, is 64+8+2+1.6 That’s 2^0 + 2^1 + 2^3 + 2^6; or a 1 in positions 1, 2, 4, and 7 of an 8-bit number: 01001011.

Byte Calculator

You can see the decimal value change as you check or uncheck each of the bits in the eight bits that make up an 8-bit byte.

(requires JavaScript)

If you have enough time on your hands, you can verify that eight bits, using powers of two, can generate all 256 numbers from zero through 255.

To see how AND and OR work, use this simple logical calculator:

(requires JavaScript)

Try putting in the values 3 and 5, and see how they turn into 1 or 7, depending on whether they’re combined via AND or OR.

How does this apply to the CoCo’s joysticks?

My question on StackExchange was about the Color Computer’s joysticks. The manual says that if PEEK(65280) returns 255, no joystick button is pressed. If it returns 126 or 254, the right joystick button is pressed. And if it returns 125 or 253, the left joystick button is pressed.

I did some tests, and happened to notice that if I pressed both buttons, I got a 252. This led me to suspect that the values we should be looking at are not the entire number, but particular bits in that number. A lot of older computers had a direct, or nearly direct, linkage between bits and hardware. A single bit can only have two values: 0 and 1. A piece of hardware whose only values were on and off, such as a joystick button, would often be linked directly to a specific bit at a specific memory location.7

A little more testing, and here’s what I found for the values of PEEK(65280) depending on which button I pressed:

byte value8 bitsbutton pressed
12601111110right button
25411111110right button
12501111101left button
25311111101left button
25211111100both buttons
25511111111no button

And the answer to my question is that, yes, there is a link between the rightmost bit and second rightmost bit and whether a button is pressed on a joystick.8 The right button is indicated by a zero in the 1st bit (2^0) and the left button by a zero in the 2nd bit (2^1).

Two to the zeroth power is 1; two to the 1st power is 2. This means that in BASIC, 1 AND <any number> will return 1 only if the 1st bit in that number is also set to 1. And 2 AND <any number> will return 2 only if the 2nd bit in that number is set to 1. It doesn’t matter what the other bits are set to. Because AND is a bitwise operator, and all but one of the bits in 1 and 2 are zero, the only bit that has a chance of being 1 (ON) in an AND with 1 or 2 is that single bit, respectively.

  • 1 in binary is 00000001
  • 2 in binary is 00000010

However, remember what actually marks that a button is pressed: it’s a zero, not a one. To put a 1 in those positions if a joystick button is pressed, I use the NOT operator. The NOT operator is also bitwise. It flips each bit in the number given. If a bit is 1, it becomes 0. And if a bit is 0, it becomes 1. This means that after using NOT on the number from PEEK(65280), a 0 in the 1st bit becomes a 1, and a 0 in the 2nd bit becomes a 1.9 At which point I can use AND on the value to detect whether a joystick button is pressed.

  • 5 CLS
  • 10 BU = PEEK(65280)
  • 40 PRINT@32,"LEFT BUTTON ";
  • 60 GOTO 10

To repeat: the “1 AND” in line 30 is checking the rightmost bit of an 8-bit number. The “2 AND” in line 50 checks the second rightmost bit. Those are the bits that are set to zero for the right joystick button and the left joystick button, respectively. By using NOT on the PEEK value, those bits will be set to 1 if the button is pressed and zero if the button is not pressed.

Line 30, then, is taking whatever number, from zero through 255, comes out of PEEK(65280), flipping each bit, and comparing the result to 00000001. Line 50 also flips the number but compares the result to 00000010.10 In each case, a bit of 0 ANDed with either 1 or 0 remains zero. If the 1 remains in the appropriate bit position after anding, it means that particular button was pressed.

For example, if the right joystick button is pressed, the value of PEEK(65280) might be 126. This corresponds to the binary value of 01111110.

  1. I apply NOT to this value. It is now 10000001.
  2. I AND this value with 1, that is, with 00000001.
  3. The result, going bit by bit is that every bit becomes 0 except the rightmost bit. So the result is 00000001. This is equivalent to the byte value of 1.
  4. I check that the result equals 1, and it does, so I know that the right joystick button is pressed.

If, on the other hand, it were the left joystick button that was pressed, PEEK(65280) might return 125. This corresponds to the binary value of 01111101.

  1. I apply NOT to this value. It is now 10000010.
  2. I AND this value with 1, that is, with 00000001.
  3. The result, going bit by bit is that every bit becomes 0: at each position, there is a zero in at least one of the compared bits. So the result is 00000000. This is equivalent to the byte value of 0.
  4. I check that the result equals 1, and it does not, so I know that the right joystick button is not pressed.

By checking the bit value rather than the byte value, it is easier to know when both buttons are pressed. Instead of checking for 126, 254, 252, or 124, we’re specifically checking the bit that corresponds to the right joystick. Similarly for the left joystick. If there are conditions where other bits than the first and second change, this would change the value of the byte but it does not change the value of the joystick bits.

For reasons that I don’t fully comprehend, bitwise manipulations have always fascinated me. I wrote a program on the TRS-80 Model 1 that would take bytes and modify specified bits based on finding a 1 or a zero in other bit positions; I can’t remember if I wrote it in BASIC or in machine code. When I switched to OS-9 on the Color Computer, I was able to turn this into a filter, probably in BASIC09, that would alter piped text by altering specified bits if other specified bits matched. I rewrote it again when I moved to an account on a Unix minicomputer, probably in C.

It was never a useful program. I’d write it, fool around with it for a bit, and then forget about it until my next computer. Probably the only times I ever seriously used it was to test it while I was programming it. Sadly, all of these incarnations are lost now. I stopped converting the program when I started using a Macintosh as my main computer, sometime in the mid nineties.

In response to TRS-80 Color Computer Programming Tools: The TRS-80 Color Computer was a fascinating implementation of the 6809 computer chip, and was, from the Color Computer 1 through 3, possibly the longest-running of the old-school personal computers.

  1. The 6809 had other bitwise operators in its instruction set, but as far as I know none were implemented in BASIC. For example, the bits in a byte could be shifted left or right, with the effect of multiplying the byte value by 2 or dividing it by two (and discarding any fractions), as long as the result was an integer greater than zero or less than 128. The 6809 also had an XOR, which was often used to display mouse cursors on the screen, for reasons which are too complicated to get into here.

  2. The NOT operator isn’t even listed in the index, probably because it has no explanation in the book. Further, the example has a typo; possibly at some point the description described OR first, then AND, and they switched it up without changing the segue sentence.

  3. Or in building blocks of eight bits. How the Color Computer builds numbers that need more than eight bits is a topic all on its own.

  4. It is also common to count up from zero, rather than from one as I’m doing here. Then, the bits are numbered zero at the rightmost up to seven at the leftmost.

  5. I’m not going to get into number bases here, but if you are familiar with the hexadecimal and octal values used by the Color Computer, it’s the same idea. Hexadecimal is base 16 and octal is base 8, just like binary is base 2.

  6. It’s usually easiest to start from the highest power of two that is less than or equal to the decimal number you’re converting. Then the next highest power of two that is less than or equal to the remainder, and so on.

  7. And hardware that produced variable values, such as joysticks, would often set an entire byte, resulting in values from 0 to 255; or would set part of a byte, resulting in values from 0 to one less than some lesser power of two. The Color Computers joysticks each produced a number from 0 to 63 (one less than 2^6) in each of the horizontal and vertical directions. The four joystick values (horizontal and vertical for the right and left joysticks) are in memory locations 346 through 349, according to 500 Pokes, Peeks ’n Execs for the TRS-80 Color Computer, page 25. But you have to EXEC 43486 first to fill those locations with a valid value.

  8. Theoretically, there is also a 01111100, or 124, when both buttons are pressed, but I never saw that value.

  9. A 1 would, of course, become a zero.

  10. If this were real code, an arguably better place to put the NOT would be when PEEKing, on line 10: `10 BU PEEK = NOT PEEK(65280)`. Line 30 would then be `IF (1 AND BU)=1 THEN PRINT "ON" ELSE PRINT "OFF"` and line 50 would be the same, replacing “1” with “2”.

    The way I’ve done it keeps all of the bitwise logic operations in one place.

  1. <- Read BASIC
  2. BASIC tokenization ->