CIA chip

T

he CIA chip (Complex Interface Adapter) is found in memory locations $dc00-$dc0f (56320-56335). Within these registers are CIA #1 and CIA #2. According to Mapping the Commodore 64, it allows the 6510 microprocessor to communicate with peripheral input and output devices. The specific devices that CIA #1 reads from and sends data to are the joystick controllers, paddle fire buttons, and the keyboard. CIA #1 has an interrupt line which is connected to the 6510 IRQ line. These two timers are used to generate interrupts at specific intervals (such as the 1/60 second interrupt used for keyboard scanning, or the more complexly timed interrupts that drive the tape read and write routines). Other features include communication with outside devices, such as the keyboard.

Locations $dc04-$dc07 (56324-56327) manage four timer registers. These registers hold a 16-bit number from 0 to 65535 in normal low-byte, high-byte format. Once the timer is activated, it begins the countdown. When Timer Counter A or B gets to 0, it will set Bit 0 or 1 in the Interrupt Control Register at $dc0d (56333). If the timer interrupt is enabled an IRQ will be set to 1. This is useful information to know especially when you start learning about raster interrupts.

The definition for the 6510 microprocessor is defined in this paragraph, according to Peeks & Pokes for the Commodore as it is known there. If you’ve ever seen an integrated circuit, you’ll know that the chip appears to have legs (total number of address lines), it can address 2^16, or 65535 memory cells (64K – as we have learned much earlier).

Each of these cells contain 8 bits, or one byte. Once the 6510 has addressed a memory cell with its 16 “legs” (address lines), it then uses 8 other “legs” (data lines) to either read or store 8 bits of data from or to that memory cell.

In machine language, mnemonics are always three characters. LDA is one such mnemonic. However, it is important to practice with machine language and use a guide such as the Commodore 64 Programmer’s Reference Guide as a mirror in order to get used to the instructions and how many parameters they contain.

Machine language is also known as ‘assembly language’. The book introducing Commodore 64 Machine Code describes it as a ‘set of abbreviated commands, words, called ‘mnemonics (which is to be discussed soon), and numbers which are the data or address numbers.

A mnemonic is a word that describes a machine language instruction. Wikipedia states it is a memory device that uses a technique that aids information retention. It is essentially an abbreviation of an instruction (as mentioned above). For example, the statement LDA reads as ‘Load the Accumulator’.

Cycles

The number of cycles will be very important as you enhance your programming knowledge and skills in machine language. This will determine how long instructions take to complete, which is especially handy when you are writing IRQ or any type of interrupts (also known as rasters). This is also referred to as “timing”, which is managed by the internal CPU clock.

In the book Machine language for the Commodore 64 and other Commodore computers, Butterfield states that most instructions run at the fastest imaginable speed. He says to count the memory cycles since that’s how fast the instruction will execute. When we begin writing code, you will see the Exce3l charts column for “Num of cycles”. This was extracted from the Programmer’s Reference Guide. This chart is a good way to see how many cycles a particular instruction takes.

Also according to the book Commodore 64 Programmer’s Reference Guide, machine language instructions either change the contents of a memory location (as mentioned earlier), or change one of the internal registers (special storage locations) inside the microprocessor. The internal registers form the very basis of machine language. Other uses of index register include temporary storage, counter, and memory load/store.

Timers

Inside your Commodore 64 are many timers that are counting up and down. Jim Butterfield states that even when you have a machine language program running, the computer “freezes” 60 times a second. The computer undertakes a special activity called interrupt processing. It stops whatever it was doing, and switches to a new set of programs that do several tasks: flashing the cursor, checking the keyboard, keeping the clock up to date, and checking to see whether the cassette motor needs power. When its’ finished, it “unfreezes” the main program and lets it continue where it left off.

The interrupt might take place between a compare instruction and branch statement. Hundreds of instructions might be executed between such statements, yet nothing is harmed. The two instructions work together perfectly to achieve the desired effect. The compare instructions (CMP, CPX, CPY) test and turn a special flag on or off (resulting in equal or not equal). This determines the route of branching (to be discussed much later). This is possible with the wonder of flags (which will be discussed next).

Registers and Flags

Registers and FlagsBefore we begin discussing and writing code, it is necessary to have a good handle on the purpose of registers and flags. These may appear perplexing at first glance, but as you begin to enhance your understanding of machine language and writing in assembly language you will eventually start to grasp their primary significance.

Below is a VICE screenshot of all the registers and flags for the Commodore 64. You can view this by clicking on the File menu and selecting Monitor or use the short cut keys Alt + m.

VICE C64 EmulatorVICE (the Versatile Commodore Emulator) is a program that can emulate a Commodore computer system environment as essential to owning the actual computer. Here is a screenshot of that tool. It can be embedded into your favorite compiler and executed in real time. However, I am unable to get this to function properly, so we will be using the Register panel in CBM Prg Studio instead.

CBM Prg StudioCBM Prg Studio (Commodore Business Machine) is a tool that is used to write in both Basic and Assembly language. Here is a screenshot for reference. NOTE: This is not a tutorial for this tool. Please use your favorite search engine for further information. This tool is used to “assemble” programs into machine language using the built in compiler. It is also color coded so it is easier to follow the instructions. For example you can identify a text string from a assembly language mnemonic (such as LDA for example).

Flag Managed Instructions

Before we go into a very detailed explanation, I thought it would be important for you to learn which instructions are managed by the flags. You can also use this for further reference as you begin your journey into the amazing world of assembly language (or machine language as it can be sometimes known as).  Information is extracted from the book Commodore 64 Assembly Language Programming.

N – Negative flag. Set when an arithmetic operation results in a negative result. The flag is controlled by the instructions ADC, AND, ASL, BIT, CMP, CPY, CPX, DEC, DEX, DEY, EOR, INC, INX, INY, LDA, LDX, LDY, LSR, ORA, PLA, PLP, ROL, ROR, TAX, TAY, TXA, and TYA.

It is set when the result byte of an operation has its high bit 7 set (showing a negative number in 2’s complement representation).

To check if a statement such as LDA #$65 sets the N flag, just convert the hexadecimal number to binary and look at the flags. If the N flag is set “on” the BMI instruction will branch, otherwise it’s ignored. If the N flag is “off” the BPL will branch.

V – Overflow flag. Set when an arithmetic operation results in an overflow from bit 6 to 7, and tells that the result will be wrong unless overflow allowed for. The flag is controlled by the instruction ADC, BIT, CLV, PLP, RTI, and SBC.

It signals the condition of bit 6 of the memory location being tested and works with the BIT instruction. If the V flag is set to “on” the BVS will branch, otherwise it is ignored. If it is “off” the BVC instruction will branch. It can be reset by the CLV instruction, however there is no instruction to set the flag.

Definition: 2’s complement (according to the Machine book of the Commodore 64).  It states that all numbers having bit 7 set are considered to be negative.

B – Break flag. Set when a programmed interrupt is brought about by a BRK instruction.

D – Decimal flag. Set when arithmetic operations are to be carried out in decimal. The flag is controlled by the instructions CLD, PLP, RTI, and SED.

Set to let the processor operate in decimal of BCD (Binary Coded Decimal) mode (not binary mode).

I – Interrupt flag. Set when an interrupt sequence is in operation. The flag is controlled by the instructions BRK, CLI, PLP, RTI, and SEI.

Set to disable any interrupt from a hardware interrupt request.

Z – Zero flag. Set when an arithmetic operation results in a zero answer. The flag is controlled by the instructions ADC, AND, ASL, BIT, CMP, CPY, CPX, DEC, DEX, DEY, EOR, INC, INX, INY, LDA, LDX, LDY, LSR, ORA, PLA, PLP, ROL, ROR, RTI, SBC, TAX, TXA, and TYA.

Set when an operation results in a zero byte or equality in a comparison. It is checked after a compare statement and the branch determines if the flag turn on (=0) or off (>0 – not equal to zero).

C – Carry flag. Indicates the presence of a ‘carry’ or a ‘borrow’ during arithmetic operations. Also set during shift or rotate operations to indicate possible loss of a bit. The flag is controlled by ADC, ASL, CLC, CMP, CPX, CPY, LSR, PLP, ROL, ROR, RTI, and SBC.

Set when an operation results in a carry/no-borrow in an addition/subtraction. It also serves as the 9th bit extension of the accumulator in a shift/rotate operation. It is sometimes used as a user flag because it is easily programmable and does not have any effect on most operations.

After a comparison the C flag is set to “on” if the register (X, Y, or A) is greater than or equal to the value compared.

Reference Material: Commodore 64 Exposed

Listed below is a screenshot I found from Wikipedia that provides a little more information in case you are still confused. Each letter corresponds to the 8 flags N, V, -, B, D, I, Z, and C.

MOS Flags

Status register (R)

This is not an instruction. Rather it is an eight bit register like the accumulator, X and Y register. It can also be referred to as the Processor Status Register or it can be found by its one letter “P”. The SR performs as if it contained eight individual bits which are used as signals or flags. The Commodore 64 only handles one status flag at a time. It will either set the bit value to “0” or “1”, or testing the status flag to see if it is set to 1 or cleared with a 0.

The zero flag is one such status flag that works with arithmetic processes. So whenever the result of a calculation is zero in the appropriate register (A, X, or Y) the Z flag is set to “1”. However, if the result of a calculation is not zero, then the Z flag is set to “0”.

The book Introducing Commodore 64 Machine Code refers to it also as a Flag register. It is used sort of as an electronic notepad. Seven of the bits in the register (8 altogether) are used to record what happened at the previous step of the program. If the previous step was a subtraction that left the A register storing zero, then one of the bits in the Status register will go from 0 to 1 to bring this to the attention of the MPC (CPU). If you add a number to the number in an accumulator, and the result consists of nine bits instead of eight, then another of the bits in the Status register is ‘set’. Each bit is then used to keep track of what just happened. You can make branch commands depend on whether a status bit is set (1) or reset (0).

Branch commands will be covered extensively later. Just know that if a branch command (BEQ – example) is “out of range”, CBM Prg Studio (or your favorite compiler) will complain and throw an error. This will usually prevent your program from being run since an error still exists.

Status Flag

Status Flag

Further elaboration (taken from Introducing Commodore 64 Machine code)

ASLThe above table shows how the bits of the Status register of the 6502 are arranged. Of these bits, 0,1, and 7 are the ones that we are most likely to use at the start of a machine code career. The use of the others is rather more specialized than we need at the moment. Bit 0 is the Carry Bit (or Carry Flag). This is set (to 1) if a piece of addition has resulted in a carry from the most significant bit of a register. If there is no carry, the bit remains reset. When a subtraction is being carried out (or a similar operation like comparison), then this bit will be used to indicate if a ‘borrow’ has been needed. It can for some purposes, be used as a ninth bit for the accumulator, particularly for shift and rotate operations in which the bits in a byte are all shifted by one place. See the screenshot above.

The Zero Flag is bit 1. It is set if the result of the previous operation was exactly zero, but will be reset (0) otherwise. It’s a useful way of detecting equality of two bytes – subtract one from the other, and if the zero flag is set, then the two were equal. The Negative Flag (bit 7) is set if the number resulting in a register after an operation has its most significant bit equal to 1. This is one type of number that might be a negative number if we are working with signed numbers. This bit is therefore used extensively when we are working with signed numbers.

You can alter some of the bits of the Status register selectively (advanced level). For the most part, we don’t load anything into this register, or store its content. It is used almost exclusively as a way of keeping track of what has just been done.

It is affected by what various opcodes do within a program.

Reference Material: Assembly language for kids Commodore 64 and Introducing Commodore 64 Machine Code

Zero flag bits

Below is a diagram of what they look like (as seen when using the Debugger in CBM Prg Studio). It has been expanded in this screenshot.

VICE Monitor

By observing the flags above (in the top window) within CBM Prg Studio’s Debugger, you can clearly see that the Z “Zero” flag is set (bit 1). You can ignore bit 5 as it is not used.

Also notice the the XR register shows $07 and that YR shows $32. As we start to work with code you will begin to understand why these registers contain such values.

Monitor Registers

The SR, AC, XR, and YR are all eight bits (one byte) in size. As we learned very early, the AC or A (depicted by “AC” in the CBM Prg Studio Debugger screenshot) register is known as the accumulator. It is the busiest place in the computer. Logical instructions, such as EOR & AND drop their results here. Most of the bytes streaming through the computer come through the accumulator. Nearly everything that occurs here will have an effect on the status register (SR).

We learned earlier that a byte ranges from 0-255. I thought it would be important to append a note here mentioned that these bytes (according to CBM Prg Studio or any C64 compiler) may be instruction codes (such as LDA, STA, etc.) which allow a task to be performed. As you will learn soon these ‘bytes’ are evaluated by your computer in sections. When the MPU (Processor) reads an instruction byte, it analyzes it to see if it is followed by other instruction bytes.  For example an instruction to LDA #1 looks like $a9 $01 (169, 1).  Others may be data bytes, which are numbers to add, store, or shift. They can also be ASCII characters to produce text on the screen. You will learn about this when we cover loops.

Byte instructions

Below is a screenshot of an assembly dump (compiled instructions) to see what this looks like after you run (known as ‘assembling’) a program.

Assembly dump

The X (XR) and Y (YR) registers are similar since they assist the accumulator. They are used as addressing indexes (to be discussed below). An example is LDA $4000, X. This instruction when used with an LDX command can cycle through memory locations as a counter is increased (INX) or decreased (DEX). Finally they must be repeated (just like a FOR/NEXT Basic loop) to reach the next available address.

Definition: Address (also known as the address number) – the electrical signals that correspond to the 0’s and 1’s. They appear as a set of connections called the address bus, which link the MPU to all the memory, RAM and ROM.

In the COMPUTE! book Machine language for Beginners, addressing is described like this. If you could peer down into the heart of the computer, you would see numbers being delivered and received from memory locations all over the computer. Sometimes the numbers arrive and are sent out, unchanged, to some other address. Other times they are compared, added, or otherwise modified, before being sent back to RAM or to a peripheral.

Stack (SP)

The stack (SP) keeps track of numbers, such as those pulled from an RTS instruction. These subroutine addresses are managed together in a list called the stack. The computer will automatically handle the stack pointer for us. All we have to do is push a number onto the stack (using PHA) and when we desire to get the result later, we simply pull it from the stack (using PLA). The most important thing is to always follow a PHA with PLA or the computer could send your program to No Man’s Land, which results in a crash, often losing your work.

Also it is important to know that the stack is organized backward in memory. It ranges from $0100 to $01ff. So the first position in the stack is at $01ff, and the last is at $0100.

In the book Peeks & Pokes for the Commodore, Abacus Software describes it as a ‘temporary storage area’ in memory.

The author from the book Introducing Commodore 64 Machine code states that the contents of the registers of the 6510 are placed into a part of the RAM memory, which is called the ‘stack’. This, incidentally, is another good reason for being careful as to where you place your machine code in the memory. If you wipe out the stack, the C64 will not like it. The stack is located in the range of memory between addresses 256 and 511. When the RTS instruction is encountered at the end of your machine code, the bytes that have been stored in the ‘stack’ are replaced into their registers, and normal action resumes. If you call a machine language program into action by any other method, not using SYS (as in Basic), you may have to attend to this salvage operation for yourself as part of your machine code program. This involves using the PUSH and PULL commands (PHA, PLA).

Card deckJim Butterfield describes the stack like a stack of documents that you may drop (or “push”) onto the stack when you take an item back again (or “pull”), you’ll get the last one that you put there. Formally, it’s called a last-in, first-out (LIFO) discipline, it’s natural and easy to understand. He also mentions that if you push three items onto the stack, be sure you pull those three items back off again. Don’t ever branch away and leave the stack littered.

A great friend in a Google Hangout (Siggy) also said you can imagine it as a deck of cards. When you take out card off the bottom of the pile (stack) then you don’t want to just toss the card away, but rather return it to the card deck later so the computer doesn’t crash.

The stack is actually quite common when using interrupts (which will be covered) later. I won’t go into detail here in order to keep this tutorial as consistent as I can.

You could actually push one thousand items onto the stack. The stack would never leave page 1 as the stack pointer went down beyond zero. It would wrap around to $ff (255) and keep going. However, you would never get those thousand distinct items back. Time for another screenshot (from Jim Butterfield’s book) so you can see this up close and personal.

Processor Status RegisterEarlier we saw a screenshot in VICE of the stack. I am showing it again here for further clarity so you can see how the computer manages the stack. This is an example of the Processor Status Register (hence the one word “Register” for abbreviation).

Currently it is pointing the stack (SP) at hex address $f6 (246). Knowing how this Processor Status Register works is the key to advancing in machine language (as I am learning).

The SR, AC, XR, and YR are eight bits in size. They are not located in memory proper. You can’t PEEK them since they have no address like the rest of memory. They are zones of the CPU.

Definition: Pointer – Looking at two bytes side by side in memory, adding them together, and multiplying them by 256 to get the base address. An example would be 0+4*256 = 1024 (screen memory start address). The 0 is one pointer and the 4 is the other pointer. Just know that a pointer always consists of two bytes (0) and (4) as in our example. The first byte is known as the LSB (lowest significant byte) and the second number is known as the MSB (Most significant byte).

The computer also utilizes a CLC before any addition. Also if adding a four to the LSB results in a carry, we want to be sure that the MSB goes up by one during the add-with-carry.  We will see examples of this when we start writing some code.

Reference Material: Machine Language for Beginners, Introducing Commodore 64 Machine Code, Machine language for the Commodore 64 and other Commodore computers, and Commodore 64 Programmer’s Reference Guide