(Article by Phaze101)
This sections is an overview of everything you need to know in relation to the CPU.
Future articles will go in further detail.
Before I start explaining the addressing modes I need to give an overview of some basic concepts that would help understanding things better.
It is time to know your numbers so if you haven’t read the first article please do so and understand the hex number system.
First let me cover what is a page. A page is a memory address from $00 to $FF, which makes each page 256 bytes long. Remember the C64 has 64K, this means is can access memory form $0000 to $FFFF. So, page zero is from $0000 to $00FF. Page one is from $0100 to $01FF. Page 2 is from $0200 to $02FF and so on.
Notice that the first byte is always indicating which page we are on. If the address is $0310 it means we are on page 3.
Please note also that since the first byte indicate the number of pages it also means that the C64 has 256 pages of memory.
From the above you need to know that Page 0 and Page 1 are very important pages. They are special pages.
Page Zero which is used a lot by the system is a very important page. It allows us to do 16-bit addressing. The CPU has got an addressing mode, called page zero addressing. We will cover addressing modes further down this article.
Page One which I covered when I mentioned the stack pointer is also a special page. This page cannot be used, and we leave the CPU to manage the stack in this area.
In theory we can use memory from page 2 onwards ($0200 – $FFFF). Having said that some of the memory is mapped or shadowed by the C64 Kernel, the C64 Basic Interpreter and other hardware things like screen memory or colour memory. For now, it is enough to know that not all memory from page 2 onwards is available to us. Memory will be covered later.
How an address is stored
An address is two bytes long or a 16 Bit Value, but a memory location can only hold one byte so two consecutives bytes are needed.
In 6502 Assembly Language, addresses are stores with the Low Order byte in the first location and the High Order bytes in the following location. That means that addresses are stored as $LLHH. (Refer to Notation table).
Try to remember this since it is very important. You will see why when explaining the addressing modes.
For the next section I created some notations that are used or commonly used in assembly language.
Addressing Modes Overview
What are addressing modes
Addressing modes is a way of using an instruction with different Operands. The Operands (or parameter format) that follow the instruction can have different formats.
These different formats are called the addressing modes.
The 6502 Addressing Modes
Here I am listing the Addressing modes as an overview.
Please note that for simplicity I am mentioning GET the value but depending on the instruction is can be STORE the value etc.
Before I start explaining addressing modes, I was in doubt weather I should cover the instruction set first and then the addressing mode. I therefore decided to go for the addressing modes since covering the whole of the instruction set would confuse beginners without knowing the addressing modes.
Do not try to learn the addressing modes by heart. It is useless. Just refer to here when you need to, in the end they will come naturally to you since things are simpler then explained and you will be using them constantly anyway.
Also do not try hard to understand the instructions presented in this article. Where necessary I will explain them via comments. The instruction set is covered in the next article. You will be coming back to this article in the future.
I consider addressing modes as a must know for a beginner. Understand these and your life in writing Assembly becomes easier.
The Addressing Modes in Detail
This is the simplest addressing mode of all. Basically, the CPU does everything for you. These instructions do not take an Operand.
For those that forgot what it is, a CPU instruction can be followed by some type of parameter but in this case the instruction takes none of this.
In this mode execution jumps to a position relative to the current address. In other words what happens here is that the Program Counter (PC) instead of executing the next instruction it jumps to a position that is relative to the current one.
The jump can be -128 bytes before the current instruction or +127 from the current instruction.
This happens in branching instructions. Although I mentioned the -128 and +127 this is for information purpose only. What is written in assembly is a branch to a label.
This is also a simple addressing mode to understand although it might sound complex.
All it is, is that the instruction like implied addressing doesn’t take any operand and it changes the accumulator content in some way.
This addressing mode is also an easy one.
The instruction is followed by a number that we specify. The hash symbol (#) is used to specify an immediate number.
As always immediate numbers can be decimal, hex and binary.
In all the above examples we loaded the accumulator with a number that we specified.
This is also another easy addressing mode to understand.
The instruction is followed by a 16-bit address memory location. This also means that we can address any of the 64K memory. We can also use a Label instead of a memory location.
Absolute Index Addressing Mode
This addressing mode is very powerful. You will use this addressing mode often.
It is used to read and write from and to multiple addresses. This addressing mode is the same as Absolute Addressing, but it adds the X or Y register to the memory location specified.
The memory location from where we are going to read or write is specified as $nnnn,X or $nnnn,Y. The Y option can be used with many commands, but the X option has more options. Changing the value of the X or Y allows you to change the memory location. The X or Y value is added to the 16 Bit address specified in the instruction.
Zero Page Addressing Mode
Zero page is an addressing mode that can address only Page Zero of memory, that is from address $0000 to $00FF.
This form of addressing mode takes less memory since the High Byte of the memory address is always zero hence it can be ignored. This is exactly what this addressing mode does. That is instead of writing $00FF to refer to memory location 256 we can write $FF which is still the same.
The assembler can also do this transparently for us. So, if you write $00FF the assembler knows you are referring to $FF and will change the instruction to a Zero Page addressing mode.
The advantage of zero page addressing mode is that is take 2 bytes instead of 3 bytes. This makes the instruction faster to execute too.
Please note that the $80 has no hash (#) in front of it hence we are not specifying a value but a memory location. Don’t let this type of addressing mode confuse you with immediate addressing mode when you specify the value yourself.
Zero Page Index Addressing
This mode is like Absolute Index Addressing but we use Page Zero. The X or Y register is added to the Zero Page address specified. The Y register is limited compared to the X Register. The Y register can only be used with LDX and STX instructions.
Important: If the Page Zero memory address plus the index register is greater than $FF the High Byte or page portion of the 16 Bit memory address will be dropped. This means that this instruction will always be execute using Page Zero memory locations.
Once gain please note the difference when we use the hash (#) and not.
Indirect Addressing Mode
We can read a 16 Bit Value from another 16 Bit memory address and use this value to Jump (GOTO) where we want to go in memory.
The jump instruction JMP is the only instruction that supports this mode.
What this means is that if location $0200 contains $00 and location $0201 contains $C0 then the instruction JMP ($0200) would jump to the instruction at $C000 (contents of $0201 and $0200). Notice the reverse order of this ($LLHH). You specify $0200 but high byte of 16-bit address is at $0201 and low byte is at $0200.
Indexed Indirect Addressing Mode
Only the X register can be used in this mode. The Zero Page memory location is added with the X register. The result of that, a 16-bit address memory location is read and a value from that 16-bit memory location is read.
Consider a situation where the instruction is LDA ($20,X), X contains $04. Also, memory at address $24 contains the value of $80 and memory at $25 contains the value of $C0. First, X is added to $20 to get $24. The target address will be fetched from $24 resulting in a target address of $C080. Register A will be loaded with the contents of memory at $C080.
Note once again that memory address $25 contains the high byte of the address and memory location $24 contains the low byte of the 16-bit address.
Indexed Indirect instructions are 2 bytes long, the second byte is the zero-page address ($20) in the example. Obviously, the fetched address must be stored in the zero page.
Indirect Indexed Addressing Mode
Only the Y register can be used in this addressing mode. This is also the most common indexed indirection mode used in the 6502 CPU.
It differs in the order that Y is applied to the indirectly fetched address.
An example instruction that uses indirect index addressing is LDA ($80),Y .
To calculate the target address, the CPU will first fetch the address stored at Page Zero location $80. That address will be added to register Y to get the final target address. For example LDA ($80),Y, if the address stored at $80 is $C028 (memory is 0080: 28 C0, remember reverse order) and register Y contains $10, then the final target address would be $C038. Register A will be loaded with the contents of memory at $C038.
Phew, that is all the 6502 addressing modes. As stated, understand these (no need to know them by heart) and programming in assembly language becomes easy.
If this week we covered addressing modes, next week will start covering the 6502 Instruction set. Not sure if it will be in one whole article or not because it is quite long also. Maybe I will decide to divide it. After the instruction set. There will be no more CPU theory, and we will jump into gaming theory. This means it will be completely hands on.
As always if you have any issues please message me. That is all for this week.
Coding is Fun 😊