02 — Numbers

This video showed how any collection of bits can be treated as a number by interpreting each bit as a digit in the binary number system. That, by the way, is where the word bit comes from: it's a contraction of binary digit.

We showed what binary and the familiar decimal number system have in common, and then looked at hexadecimal.

The key thing to take away is that you should use whichever representation makes sense: decimal if you're counting or doing arithmetic, binary if you're turning things on and off. Except experienced programmers use hexadecimal as a shorthand for binary; much easier than counting 1s and 0s.

As a trivial aside, the inventors of computers enjoyed word plays. They had a good reason for the name bit, then played word games to come up with byte and nybble (or nibble). Similarly, they took hardware, which makes perfect sense, and gave us software, which only makes sense as a play on words. And software that is closely tied to the hardware is called firmware.

Counter

0 MOV  #0,PORTB
1 WAIT 5000
2 ADD  #1,PORTB
3 JMP  1

Feel free to experiment with the delay. Even this slow computer counts pretty quickly if you set the delay to 0. You might also find it interesting to try adding different numbers in slot 2. If you use #4 instead of #1, the two lowest bits don't change, but the others count much more quickly. If you think about the bit pattern for 4, it should be pretty clear why this happens.

Other Number Representations

There are many, many ways numbers have been represented in computers. Let's look at a couple of them.

Signed Numbers

The numbers we've explored so far are unsigned binary numbers; they can't represent values less than zero. Obviously computers can can deal with this. The usual representation for signed numbers is 2's complement numbers. In days gone by there were also 1's complement numbers which had the interesting property of having representations for +0 and −0.

I think the easiest (and seldom seen) way of thinking of 2's complement numbers is that the leftmost bit is the negative of its usual value; all the other bits still have their positive values. So in a 4-bit signed number, 1000 is −8, 0111 is 7 (as usual) and 1111 is −8+7 = −1. No matter how many bits, a 1 followed by all 0s is the most negative value, and all 1s is −1.

The fun thing with 2's complement (and the reason we don't see much of 1's complement) is that it works exactly the same as unsigned for adding and subtracting. Staying with 4-bit, if you add 1111 (unsigned), you'll always end up with one less than the value you started with. As mentioned in the video, it's like a car odometer. If you drive the car 999 km on an odometer that only has 3 digits, it's like you went backwards 1 km.

This means that, once again, it's for the programmer to decide whether the bit pattern is a signed or unsigned number. ArdEx's ADD and SUB instructions work just as well with either.

To keep ArdEx simple, I left out the usual supports for signed number operations, but it is possible to do signed arithmetic without them.

Binary Coded Decimal Numbers (BCD)

I've rarely used BCD myself, but this was a popular representation in commercial accounting systems. Might still be. And I know that it's used in calculators.

The easiest way to think of it is that it uses hexadecimal bit patterns, but only for valid decimal digits. As you count up, you reach 0x09 and rather than follow that with 0x0A, you go to 0x10, just as if it were decimal.

This seems like drawbacks all the way. You're using 8 bits, which has room for 256 values, but you're only using them to hold 100 values. In other words it wastes space. It's also messier for the programmer. Each time you do a calculation you need an extra adjustment phase in case one of the digits ended up in the A-F range. However, the big advantage of BCD is that, because everything is calculated in decimal, it will end up in perfect agreement with a human using pencil and paper. Admittedly, this isn't a problem with whole numbers, but when you start rounding off fractions, differences emerge.

One of the later videos will look at fractions and some of the pitfalls when computing with them.

ArdEx has no built-in support for BCD numbers, but that doesn't mean you can't use them. You would just have to give them some more thought and write some more code. I described them here just as a point of interest, and to back up my claim that there are many ways to represent numbers using bit patterns.

Further Experiments

These are just suggestions to help you get some feel for how hex is a binary shorthand. The last couple are pretty geeky, so marked in red.

  1. In decimal and in hex (using the BASE command if you wish), what is the largest number that can be stored in 4 bits?
  2. In 5 bits?
  3. In 6?
  4. In 8?
  5. In 16?
  6. How do those numbers relate to powers of 2?
  7. What is 1,000,000 in hex? (Warning, ArdEx will complain. You'll need to divide and conquer.)
  8. How can you tell if a binary number is odd?
  9. How can you tell if a binary number is divisible by 32?
  10. Most people know that you can work out the remainder of a number when divided by 9 just by adding up its digits. E.g. the remainder of 488 divided by 9 is 4+8+8 = 20; 2+0 = 2. Sure enough, 488 = 9×54+2. Something very similar happens in hex. The remainder when divided by 0xF is the sum of the hex digits. So 0x3A8 would be 0x3+0xA+0x8 = 0x15; 0x1+0x5 = 6. Verify this using the BASE command and a calculator (or your brain if you want to show off).
  11. More useful than the remainder when divided by 0xF is knowing the remainder when divided by 0xA (handy for converting hex to decimal).

    I've never seen it used, but here's the rule: Add up all but the rightmost hex digit. Multiply by six. Add the rightmost digit. Repeat until down to one digit. So, 0x3A8 gives:

    0x3+0xA = 0xD; 0xD×6=0x4E; 0x4E+0x8 = 0x56;
    0x5×6 = 0x1E; 0x1E+0x6 = 0x24;
    0x2×6 = 0xC; 0xC+4 = 0x10;
    0x1×6 = 0x6; 0x6+0 = 6.

    Well, that probably explains why I've never seen it used! (To be fair, there are a number of simplifications available which you are welcome to think about). The question is, can you explain why it works? (Big hint: what are the remainders of the powers of 16 when divided by 10?)

Required Equipment