T

his is a brand new session that follows my YouTube channel tutorials series for “C64 Machine Language Tutorials”. You will definitely want to refer back to this section time and again as it contains a wealth of information for beginners and experts wanting to learn more about how to program in machine language for the Commodore 64.

Note: The author of this website can receive a compensation for promoting, reviewing, or recommending products to viewers.

The information found here spans from multiple Commodore 64 books. Some of these include Mapping the Commodore 64 & 64C, Commodore 64 Assembly Language Programming, Introducing Commodore 64 Machine Code, Machine Language for the Commodore 64 and other Commodore computers, Machine Language for Beginners, Commodore 64 Exposed, Intermediate Commodore 64, The Super Computer Snooper, Assembly Language for kids Commodore 64, Commodore 64 Programmers Reference Guide, The Machine Language Book of the Commodore 64, Peeks & Pokes for the Commodore 64, and Commodore 64 Assembly Language.

C64 Machine Language Tutorials consist of a series of instructions that execute a task at a much faster speed than a program written in Basic for example. This is because it is native to the computer’s language and doesn’t require any interpretation as is common with  Basic.

A program counter (PC) increments the program instructions. It is a 16-bit register that can record a full sized address number all the way up to 65535 ($ffff). Each instruction may increment the program counter by one or more counts.  The program counter is identified with an asterisk (* =) in most machine language editors.

A typical counter may look like * = $0801 when looking at a Commodore 64 machine language example. Essentially the program counter is setting a starting location for its’ memory at address $0801 (2049 – decimal).  The example seen above is a screenshot from the CBM Prg Studio editor.

ROM and RAM

Memory must be unreserved at the PC to prevent any crashes with the program Also memory in ROM cannot be overwritten. Trying to write in ROM and then in empty areas will leave gaps in your code. ROM stands for Read Only Memory. This is memory that is used by the processor, video chip, etc. RAM represents Random Access memory. Your computer’s memory can be stored here in Basic and machine language program without causing any conflicts.

Accumulator

The definition of the accumulator is defined as the “doing” register of the MPU (Microprocessor unit), according to Jim Butterfield. The MPU is the Commodore chip that performs the processing. Sometimes this is a 6502 chip, 6510 and so on. It just depends on what chip is contained in your system.

Various machine language instructions allow you to copy the contents of a memory location into the accumulator, copy the contents of the accumulator into a memory location, modify the contents of the accumulator, or some other register directly, without affecting any memory. The accumulator is the only register that has instructions for performing math.

The MPU can load a byte, meaning that a byte which is stored in the memory can be duplicated to another store in the MPU. It can also store a byte, meaning that a copy of a byte that is stored in the MPU can be placed in any address in memory. A byte can contain a value between 0-255 (more will be covered later).

The MPU also contains a logic set. Logic actions compare the bits of two bytes and “produce an answer” which depends on the bit values that are being compared and on the logic rule that is being followed. The three main logic rules are called AND, OR, and EOR.

Another set of actions is called the jump set. A jump means a change of address, rather like the action of GOTO in Basic. Essentially it can jump to a particular place in memory (inside the program).

6510 ChipThe microprocessor can be programmed by sending it electrical signals. That is the purpose of C64 Machine Language Tutorials, which is to carry out a set of instructions. The chip seen here may be housed inside your system. You may also like to think of it as a robot being programmed to do whatever you ask. However, you have to be very specific. So if you tell the robot to open the door, it will actually first have to walk over to the door, extend its metallic arm out, grab the door knob, turn it, and push it open before the door will budge. Machine language accomplishes this with a lot of repetitive instructions that are embedded together to create instructions to carry out a specific task.

System Memory

Before we delve into the instructions, it is important to understand how memory on the Commodore 64 works. Your computer is 64k. The k is known as “kilobytes” which is equal to one thousand. The Commodore 64 can communicate with 64k or 65535 (64 * 1024) bytes of memory. Each of these bytes of memory can store a number from 0 to 255. The system can sometimes read  and write information from any of these 65536 locations by using its’ address, a number from 0 to 65535.

Bits

Each byte is made up of eight binary digits called bits. These bits are the computer’s smallest unit of information. They can contain only the number one or the number zero, but when combined, they can be used to form any number indeed.

A single bit can only be a one or a zero. If two bits are combined though, the number increases. Some examples would look like 00, 01, 10, 11. When eight bits are put together, the number of combinations increases to 256. These eight bits are called a byte and can be used to represent the numbers from 0 to 255.

Binary

The system of numbering is known as binary (or base two). It works much like the decimal (base ten) system. In the base ten numbering system, the rightmost digit is known as the one’s place, and holds a number from 0 to 9. The next place to the left is known as the ten’s place, and also holds a number from 0 to 9, which represents the number of times the one’s place has been used in counting (the number of tens).

In the binary system, there is a one’s place, then a two’s place, a four’s place, etc. The bits are counted from right to left, starting with Bit 0. Here are the values of each bit.

If all the bits are added together (128+64+32+16+8+4+2+1), they total 255, which is the maximum value of one byte.

Hexadecimal

It is also important to learn what hexadecimal addresses are. I have included information found in the book Mapping the Commodore 64 below for more clarity regarding this guide on C64 Machine Language Tutorials.

One other numbering system that is used when speaking about computers is the hexadecimal (base 16) system or hex for short. Each hexadecimal digit can count a number from 0 to 15. Since the highest numeric digit is 9, the alphabet must be used: A=10, B=11, and so on up to F=15. With just two digits, 256 combinations are possible (16 * 16). That means that each byte can be represented by just two hexadecimal digits, each of which stands for four bits of memory. These four-bit units are smaller than a byte, so they are known as nybbles.

Hexadecimal to DecimalSince programmers often find that hexadecimal numbers are easier to use than binary or decimal numbers, numbers in machine language are often written in hexadecimal. A $ (dollar sign) donates that a hexadecimal value will follow. We will see examples of these when we start writing programs. Below is an example of Hex and Decimal digits.

You can use the Windows calculator to convert numbers from hexadecimal to decimal if you are still getting used to them as I am. Just be sure to set the calculator mode to Programmer (you can do this by clicking on the View menu and select Programmer or just press Alt + 3. Below is an example of hexadecimal. Setting the radio buttons on the right to Dec will allow you to see the decimal value.

If you are curious of how to do the conversion yourself, I have included some information found in a resource book.

  1. Step 1. Take the leftmost digits. If it’s a letter from A to F, convert it to the appropriate numeric value (A equals 10, B equals 11, and so on).

  2. Step 2: If there are no more digits, you’re finished; you have the number. Stop.

  3. Multiply the value so far by 16. Add the next digit to the result, converting letters if needed. Go back to step 2.

Using the above steps, let’s convert the hexadecimal number $12AC

  1. Step 1. The leftmost digit is 1

  2. There are more digits, so we’ll continue

  3. 1 times 16 is 16, plus 2 gives 18.

  4. More digits to come.

  5. 18 times 16 is 288, plus 10 (for A) gives 298

  6. More digits to come.

  7. 298 x 16 is 4768, plus 12 (for C) gives 4780.

  8. No more digits. 4780 is the decimal value.

Using the Windows calculator you can also see the octagonal and binary values. I have included a screenshot showing 127 in binary for this example of C64 Machine Language Tutorials.

6526 ChipThe chip can see the entire 64k of memory. If you want to use more you will have do something called “bank switching”, however this is better reserved for another tutorial. Essentially “bank switching” allows you to access large portions of memory thanks to the 6526 Complex Interface Adapter Chip #2 (CIA #2). Seen here is a picture of that chip for reference.

When I was first learning Commodore 64 Assembly language I found that purchasing a good book is a must have. I have even included a screenshot here to show you that I have a lot of them on hand already. Nothing beats a good book, especially learning about game design and programming for the Commodore 64!