(Article by Phaze101)
With this article we have reached the section where we will be switching from theory into practice. We will be using CBM Prog Studio. I will not be wasting time in explaining how to download it, install it and configure it. There are too many videos on YouTube regarding this. If there is a need to explain one of its features or assembly directives, I will explain it when we encounter it.
You can download CBM Prg Studio from here
Please note that from now on it will be hands on. The listings will be images so that no one can do cut and paste from the article to the assembler. I need you to type the code. Only if you practice typing in the code like the old days when copying listing from magazines you will learn what you are doing. Sorry if this is going to put some off you of but it is for your own good. If you really want to learn assembly, you need to have patience. As I said in article one only if you have patience you will succeed in learning assembly. Of course, for those that know it all this might sound absurd, but these articles are aimed at beginners who seriously want to learn assembly. So, if you are serious in learning assembly you will make the effort, to type the listing and have patience.
Soon, who you might see me as your teacher, or your master will be superseded by you. When that happens, I will be more than proud of what you have learnt or achieved in terms of this assembly course. I will know that my work was not in vein. Then I will be able to learn from you and you’ll become my teacher 😊
Let’s recap sometime that we covered in articles 4 and 5. In article 4 we explained the Addressing modes and in article 5 we covered the instruction set.
Now to those that are still confused let’s cover what is the relation or association between the two.
Let’s take one instruction and see how addressing modes and the instruction fit together.
As an example, let’s us LDA which by now you should know it stands for Load Accumulator.
The LDA instruction can use the following addressing modes followed by an example
- Absolute mode – LDA $C000
- Zero Page – LDA $FA
- Immediate – LDA #$01
- Absolute Index X or Absolute Index Y – LDA $C000,X
- Pre-Indexed Indirect X – LDA ($FB,X)
- Post Index Indirect Y – LDA ($FB),Y
- Zero Page Index – LDA $FA,X
How did I get all this info? Well I looked it up on the internet or in one of the books on the 6502. I personally do not remember all by heart although by time things will come natural and why I insist you type your listings.
Here are 3 links that explain the instruction set and the addressing mode each instruction can do.
Below is a screen capture from one of the sites for LDA which we will use as an example to explain the meaning of it all.
At the top left row, you can see that it is moving the contents of a memory location to the A register. M -> A
On the top right corner, we see the Status Register flags that this instruction can modify. N and Z in this case.
From the above table you can see that as stated it supports the addressing modes mentioned earlier and gives also an example of the addressing mode.
Next column is the Opcode of an instruction. This is the number you see when you do a disassembly of a program. Each addressing mode for the same instruction has got a different number.
The next 2 columns are used for code optimization and speed. We won’t go much into this, but it is good to know.
The bytes column shows how much memory it takes each addressing mode for the same instruction.
The cycles column shows how many CPU cycles it takes this addressing mode for the same instruction.
You will notice while going through the instruction set that some instructions support very few addressing modes. There are many instructions that support only one addressing mode such as implied addressing.
When you have doubts always refer to the 3 links above. When doing optimization, you will have to refer to the instructions set to get the correcting number of bytes or cycles.
We hear a lot of talk on 8-bit computers about code optimization and speed.
Well let me explain a few things that can surprise you. Ignore all this since you are beginners. Have you heard me, ignore it? Why? Simply because unless you have run out of memory or need more CPU cycles to have some mega cool effect you do not need to worry about it. Do not let these buzz words influence you. No one is in a race here. In assembly you won’t look cool if you saved 2 bytes when you still have 30K of ram. You won’t look cool if you have a routine that writes some text on the screen saying game over which is faster than someone’s else. There are times when you will need more speed but till then do not bother. The most important thing is that you write routines that work and are bug free. Optimization and speed come after if needed. I am sure that there are others that do not agree with me on the above, it is my opinion but being a beginner do you seriously want to waste your time trying to optimize when you have no practice yet.
Now there are two types of optimizations. One is for memory and the other is for speed.
Sometimes you can optimize code for both, that is memory and speed. However most often than not it is either speed or memory, so you decide depending on the code or issue you have in front of you.
A game is divided or made of from several parts. You can divide these parts in screen to keep things simple.
Let’s take a simple game. You normally have the
- Opening screen where it normally waits for you to press a button and start playing.
- This opening screen might also provide access to the help screen where you get the instructions of how to play the game and go back to the main screen.
- When you press the button on the opening screen you are taken to the game.
- During the game (called also the game loop) various things happens like moving the player, moving the enemy, collision detection is checked, depending on collision detection certain factors take place, like the score is updated or the player lives are updates etc. This continues and on till the player has no more lives.
- When the game ends the game over screen shows up.
- After the game over screen one might be taken to a high score table and again you are taken back to the opening screen.
Why I am covering all this? In this initial part of the series I will be showing you how to create 1, 2, 3, 5 and 6.
We will skip the game loop for now, but we will get back to it once the first bit of game concepts are done.
Programming Commodore Hardware
Through our series we will be accessing many times the hardware directly. Most of you are already doing it using Basic Peek and Poke.
When we will be accessing the hardware, I will ty to explain most of the things but a book that you constantly need besides you is the Commodore 64 Reference manual. Although I am sure there are gurus out there that know the hardware registers by heart it is not something that you need to know. If you understand what the hardware register do it is fine.
So enough about all this talking, as promised you let’s get your hands dirty and start using the assembler.
Explanation of My Coding Style
My code is heavily commented. I even say which books I used or referenced in the code and their page.
I believe in commenting the code however when typing it in you do not need to type all the remarks. They are there to help you understand the code.
Also, there is code that you should type it in as is and you do not need to understand for now what it is doing. Currently this is the code that waits for the spacebar to be pressed. Please do not waste time trying to understand it. In future I will be explaining how to handle the keyboard.
I also do not like using the JMP instruction. I do not like GOTO in BASIC and same in assembly. I believe (my own opinion here) the GOTO and JMP can create what is called “spaghetti code”. Please look it up on google if you do not know what “spaghetti code” is.
Where possible I divide each small thing in a subroutine and a sub routine can have multiple subroutines in it but in the end, they all return to the same subroutine. So, I am a heavy user of the JSR. I feel that code is more organized if I use this instruction.
What I mean by this? If you look at our first example code, I have a routine called JSR WaitForSpace. I could have inserted the WaitForSpace code in the same main code but I preferred it to be isolated so you can focus on the main code and ignore the WaitForSpace code. Here is the Code for WaitForSpace.
As stated earlier please type this code as is without the remarks and do not try to understand it.
As you also see this creates small code blocks so when debugging (we will do this in future) it is easier to debug.
All the code we do for this section of the series will start at memory location 49152 ($C000) so you will be typing SYS 49152 to start the program. My tutorials do not include this code that you can add to the code from CBM prg studio for a reason. This is my preference.
Why we use $C000. Well the C64 has 4K of memory that is protected from Basic. Our programs will not be bigger than 4K hence why it is convenient to use this memory location.
I will be ignoring all my own remarks and only explaining code that needs to be explained. The remarks are there to help you understand better.
For those that do not understand English the comments in the code will not be translated into Italian. Please use google to translate them however most of the things are explained in the article anyway. This is extra work that is not need.
Please note that I use remarks followed by a series of equal sign (=) at top and bottom of a comment block. I use comment blocks to explain the code block that follows and mark the beginning of a new block of code.
My coding style is my own preference. You can select your own. Just want to explain it that is all.
The next two tutorials that follow do nothing spectacular however they are here to get you used to typing assembly code in the correct format in the assembler.
First Program – Code 01
Here is the main basic code that you need to understand.
Let’s go through this and explain it all.
Everything in green is a comment first of all.
The first thing you will see is the * directive. This is not an CPU instruction but what is called an assembler directive. Basically, you are telling the assembler where in memory your code will be stored which in this case it will be at memory location $C000 or 49152. So, SYS 49152 will execute our code.
The next thing that come up is the Label Start. This is a label that specifies that the start of our program. We do not use it in this case but I like to label the start of program, so it is a case of habit here.
The next 3 instructions are very interesting. The first one LDA #$0 means load the accumulator with a value of 1. We are using immediate addressing here. Notice the hash sign (#) which as explained in article 4 it means the value that follows.
The second and third instructions are very easy. They are used in Basic constantly to change the Background colour and the Border colour. You might not recognize the $D020 and $D021 but if you managed to convert the hex numbers to decimal you will realise that these number are the famous 53281 and 53280 respectively. So, what we are doing here?
Well we loaded the accumulator with the value of zero which is equivalent to black. We are telling the CPU to store a zero (black) in memory locations 53281 and 53280 respectively. It is the same as doing the Poke commands in basic.
The next command is a jump to subroutine JSR. It simply executes the code that waits for us to press the spacebar. If the spacebar is pressed the next instruction is an RTS which means return to where we left with SYS49152 hence return to BASIC. The program has finished executing.
When we run this program with as always from now on SYS 49152, we get the below. The program will wait for you to press the spacebar to give you the READY prompt.
Try modifying the program to have different colour for border and background.
Here is the full basic listing of the first assembly language (no copy and paste sorry allowed 😊 )
Second Step – Code O2
Let pass to tutorial 02.
This code creates the same effect that you see in many loaders. To be fair it is simpler than the previous tutorial.
We only have one Instruction which is INC \$D020. Basically, we are incrementing the value at \$D020. It doesn’t matter that the increment passes the colour no 16, the high nibble of the byte is ignored and hence only the first 4 bits are used which gives us the color from 0 to 15. When the value of \$D020 reaches \$FF it starts again from zero.
Remember run your assembled code with SYS 49152 and to press the spacebar to exit from the code.
Here is a full listing of all the code.
That is, it for this week. These tutorials should get you started in typing some assembly code. Learn the format of assembly. Get used to some of the errors the assembler display. Learn to use the help of CBM Prg Studio to understand what it is trying to tell you.
Next week will examine different ways of the first routine that we need to have and know for our game. It is used frequently in a game.
As always if you have any issues please message me. That is all for this week.
Coding is Fun 😊