Learning Assembler 6502 makes you a better developer?

Posted: February 11, 2014 in 6502, Commodore 64, Programming

In my journey to learn everything about the Commodore 64 I did some experiments in BASIC and I managed to finish a complete game. Although I believe the final product was pretty good, every article I read in magazines like Compute Gazette keep saying that you can get most of the machine if you code in its native language: 6502 machine language. This kind of bothered me a bit because I never had a chance to program using any assembler. I did a quick training on Z80 back in 1984 but I never use it – and to be honest, it didn’t click on me – I was way more comfortable using BASIC.

BASIC has a lot of problems, like the lack of functions and better structured statements, but it is easy to learn and you can see the immediate results of what you’re coding, which is probably the reason of its huge success. I know I can still do amazing things using plain BASIC!

To answer the title question, I say a big “yes”! Learning to code for the 6502 will make you a better developer, even if you don’t actually have a reason or use for it right now. Here are my reasons:

  1. 6502 is a 8 bit microprocessor with a limited number of instructions, make any ordinary human being be able to learn it.
  2. Completing the previous item, there is no built-in multiplication or division routines, so you have to learn how to do it. Of course you can get one of the many ready-to-use routines available, but at least you will have a better understand on how to overcome basic limitations.
  3. The commodore 64 (or any other 6502-based computer) is a machine with very well-known feature set. It is not hard to learn and understand how to use some of the machine inner “secrets” (interrupts for example) to make your application.
  4. 6502 instruction set doesn’t have many registers to use, so you have to learn how to be creative, use the stack and memory in an efficient way
  5. Machine language is very hard to debug, which demands a well-organized and commented code. It can cost you hours or days to find out a bug when you code in machine language, and if your code is a mess, you might never found it!
  6. Commodore 64 has a good set of awesome features, like hardware based sprites and collision detection, SID chip, etc… which makes a bit easier to accomplish simple tasks like moving your players around the screen.
  7. Machine language will allow you to unleash all the power the Commodore 64 has to offer. Although this is not a reason per se, I believe that when you see what the machine can do, you will wish to learn more and more how to code efficiently

The reasons above are from my observation of the past two weeks I’ve been spending learning and trying out few 6502 routines.

My point here is not compare the two languages, but to illustrate some of the reasons above, let’s do exactly that. Let’s see how would one implement a code that prints a message on the screen in BASIC and ML. The task is pretty simple, we are going to display at the top left corner of the screen the message “HAPPY 1985!”

In BASIC this is very simple. Probably the very first BASIC command one could learn is PRINT, which will display something on the screen. It is also common knowledge that to print at the top left corner you have to clear the screen, or at least move the cursor to that place – we are doing the latter just to keep things simple. This is how the small program will look like:

10 PRINT "{home}";
20 PRINT "HAPPY 1985!"

The line 10 prints the home character, which will look like a reversed S on your screen. The semi-colon after it will keep the cursor positioned at the same place. The line 20 prints the string. Pretty simple, eh? As you can see here, BASIC will demand the knowledge of a single command, and that the string you want to display has to be placed between quotes.

When going down the bit lane, the story is different. When coding in machine language, you have to dig deep into the details. Each step has to be well thought, and some questions have to be answered:

  • What is a string?
  • How is it stored in memory?
  • How to display the string?
  • Where to put the message?
  • Do I have a single command to display the message as a whole?

The machine language for the 6502 doesn’t know what is a string, it knows how to handle bits, bytes, memory addresses, and that is it. So in this case you have to know that the string is actually a chain of bytes in a certain memory address in RAM. Since there is no command to display a string, you will have to display one character at a time. In case of the C64, the video is also mapped to some address in the RAM. The default address is 1024 ($0400) for the first position and so on.

In addition, the 6502 have one accumulator and two register to manipulate any data, plus the RAM to store data as well. Our program logic has to use only these resources.

This would be the ML equivalent code for the BASIC commands above (using CBM prg Studio syntax):

start  LDX #$0          ; <em>initialize register X with 0</em>
cycle  LDA hworld,X     ; read content of hworld+x and put into accumulator A
       CMP #0           ; is it zero?
       BEQ exit         ; if so jump to exit (i.e., returns)
       STA $0400,X      ; put the byte stored in A at the address $0400+x
       INX              ; increment value of x to read the next character
       JMP cycle        ; go back to cycle.
exit   RTS

hworld text 'HAPPY 1985!'
       byte 0

The label hworld points to a memory address specified when the program is build. As an example, lets suppose it represents the address 49169 ($c010). That means that the string will be placed at the address 49169 to 49179, and a byte 0 placed at the address 49180 to be used as a end-of-string mark.

That single BASIC line that prints the string is implemented here as a loop starting in cycle, reading one character at a time, and placing them at the video RAM address. The ML code above is not necessarily complicated, but it is a bit more complex since it has to deal with the machine resources at an almost atomic level.

An old example about applying both logics in a real life task illustrates really well those differences:

BASICGo to the fridge and get me a glass of water.

Machine LanguageWalk north 10 steps, turn left, walk 2 steps, open the cabinet, pick up a glass, close the cabinet, turn 180 degrees, walk 4 steps, grasp the fridge door handle and pull it, search for the water bottle, pick it up using your free hand, pour the water from the bottle into the glass, … ok, I think you get it by now!

The fact that the machine language demands a more detailed and granular instructions, it  forces you to be more attentive to details, and how to handle each resource available or necessary to complete the task.

It doesn’t mean that you have to do all the heavy lifting all the time to be considered a good developer – that’s not the point. I really believe that there is always the right tool for the right job, but if you have the opportunity to learn the hard way, you have only to win.

How about you? Do you agree or have something else to say?

Advertisements
Comments
  1. […] seja lá qual for o nome, este excelente artigo no blog C64 Programming do braso-canadense (outro???) Paulo Garcia lhe dará a exata idéia do que […]

  2. Radek Kujawa says:

    Is there really a point in doing CMP after LDA ? As far as I understand LDA is also functionally equivalent to CMP in this case.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s