Math Basics Part 1 - Know your Numbering Systems
You don't like Math? Nor Do I, but...
...with Machine Language we use the shortest path to communicate with the C64 hardware. What we do is very low level and the C64 expects that we are comfortable with its way of getting data stored and manipulated. The key to not be too overwhelmed is to start with just the amount of Math required to get around the system - and believe me, it is actually not that much. I will make this as brief as possible.
Three numbering systems to rule the C64
Of course you are aware of using the Decimal numbering system. We use it since the dawn of civilization because human beings have 10 fingers. What you did not learn since Kindergarten though is dealing with the Binary and the Hexadecimal numbering systems. Coding the C64 requires an understanding on when to use which of the three and how to convert from one to the other.
As an average C64 user you would probably only deal with Decimal numbers as the BASIC interpreter has no out-of-the-box capability for any other notation. This is one of many flaws in the shipped BASIC interpreter and makes for example Bit manipulation via BASIC unnecessary difficult. Anyways, as a 6502 coder you will rarely encounter Decimal notation but to understand the other two systems, let's refresh our knowledge and look at a Decimal number first.
The Decimal System is also known as "Base 10" since it is based on 10 digits from 0 to 9. When you count up starting at zero the Decimal system requires to add a 1 to the left of your number after reaching 9 and then restarts counting the units again from zero.
Each digit in a Decimal number has a position. The Decimal Point is our only indicator to know which position is which. So even a number like 25 has a Decimal point which is hidden by a short cut in writing we are used to. The correct notation would in fact be 25.0.
Every position further to the left of a Decimal Point is 10 times bigger, every position further to the right is 10 times smaller.
Binary notation is what our C64 understands because it uses electrical signals. The Bit is the smallest information unit and technically a Bit set to One indicates there is a high voltage level and a Bit set to Zero indicates there is a low voltage level from an electric signal. So actually Bits are never "off" - unless you turn off your computer. They are either set to a high or low voltage. By the way there were computers a couple of decades ago which worked with three states (-1, 0, +1) called Ternary systems. They were considered to be superior to the ones based on a Binary numbering system but like with VHS and Betamax - the better product must not necessarily win the market.
Except for the fact that we deal with Zeros and Ones there is no real difference to the explanation on on the Decimal Numbering System, we now work in a "Base 2" system. If we start at the right and go left one position the value of a Number multiplies by 2 instead of by 10. Same goes for the other direction which will divide in half. Look at the example.
This Binary number has 8 positions. Each Position has a value to the Base of 2. If you know the Decimal values represented by each position, then converting a Binary number to Decimal is very simple. Just add up all values where the Binary position is set to One. In the case above 1+4+16+32 adds up to the number 53 which we now know represents %00110101 in decimal notation.
I chose a number with eight positions not by accident. In In the "8-Bit" world this length represents a Byte. The Commodore C64 has 65536 memory locations where into each we can write one Byte of information. Half of a Byte is also called a Nibble. This additional representation will come handy when dealing with Hexadecimal numbers.
As you might have noticed already, Binary numbers are usually prefixed with the % sign to not confuse them with Decimal or Hex numbers, e.g. %10 represents the Decimal number 2.
Hexadecimal (or short: Hex)
The Hexadecimal numbering system is the one you will deal with most of the time in addition to manipulating individual Bits in a Byte. Since we need 16 different individual digits to represent a so-called "Base 16" number, Hexadecimal borrows in addition to the numbers from 0-9 a few letters from the alphabet, namely A, B, C, D, E and F. Let's look at the Hex Number $314.
If you look further at the conversion table below you will realize something very interesting. To represent a Nibble only a single-digit Hex number is required. Thinking forward, an 8-Bit number can be represented by a two-digit Hex-Number and a 16-Bit number can be written with only a four-digit Hex number.
Again, this is very important: with just a 4 digits wide Hex number we can access any location in the C64 memory as all 65535 locations in memory can be addressed with a Hex Number from $0000 to $FFFF.
This is awesome! It saves us a lot of typing work and working with Hex is especially with bigger numbers or memory locations much easier than using a Binary basis. To not confuse Hex Numbers with Binary or Decimal Numbers, the numbers are prefixed with a $ sign.
Since it is so straight-forward to use Hex numbers to represent Binary notations it is the common numbering system we use during development in our editor. $314 is just much easier to remember than %001100010100, is it not?
All principles of Decimal and Binary systems apply to Hexadecimal of course.
- Decimal (Base 10): the decimal system is sort of only relevant in BASIC as the BASIC interpreter has no out of the box methods to notate to any other Base.
- Binary (Base 2): When we manipulate individual Bits or inspect the content of a Byte, we need to deal with Base 2. We do this very often because of the memory-mapped I/O nature of the Commodore C64. Many Bytes are technically used as Dip Switches to do configuration in the I/O chips. Learning how to manipulate Bits is key to master the machine.
- Hexadecimal (Base 16): Hex is actually a helper for us to not have to deal with long chains of Zeroes and Ones. Using Hex notation saves us a lot of typing work. In the end, a compiler will translate our Hex numbers in the source code to binary notation though as the C64 does not understand any other system.