In ancient times, a game programmer developed his or her game using assembly language. A popular form of assembly language at one time was that for the 6502, used in the Nintendo Entertainment System, the Apple II, and the Atari 2600.

Assembly language is considered one of the hardest forms of programming to learn. It’s not strict on data types, meaning there are no integers (signed counting numbers), floating points (numbers with decimals), characters, or strings (text). In assembly language, you are in control; all data is represented as bits, bytes, and words. You can store whatever you like in a memory location without worrying about the assembler generating an error. It’s up to you to remember what kind of data type is stored where.

What I personally like about assembly language is that all the instructions are short hand; they don’t take more than a few characters of space. Source files are not cluttered with long lines of code. A line of code does not continue on into another line of code. Usually in other programming languages, programmers notate a single line of code by creating a newline and using indention to mark that the two lines of code are indeed the same line of code.

In assembly adding a number to another number is performed like so:

LDA #64
CLC
ADC #32
STA $00

The first line loads the number 64 into what is called the accumulator: a part of the processor used for loading, storing, and performing arithmetic on data. The second line prepares the accumulator to perform an addition operation by clearing what is called the “carry bit.” The third line adds 32 to the contents of the accumulator (64), and finally the fourth line stores the contents in memory location $00. In a programming language like C/C++ this same operation would be performed like this:

char *x = (char *)0x000000;
*x = 64+32;

As you can see, it isn’t any more complicated in C than it is in assembly, but the advantage of C is you can create variables or memory locations on the fly, where in assembly you might have to manually keep track of them.

What makes 6502 assembly complicated is when the programmer is forced to deal with multiplication or division. The 6502 does not have the built in capabilities for multiplication or division as it does for addition and subtraction. It does however provide bit operations that can be used to pull off multiplication and division, for example:

LDA #64
ROL

On the first line I loaded the accumulator with the number 64, then shifted the bits over to the left one digit. In binary the number 64 equals 01000000 (notice the 8 bits?), when I moved the bits over to the left it became 10000000, or the number 128. A left bit shift operation is equivalent to multiplying a number by 2. When shifting bits over to the right one digit, that is equivalent to dividing a number by 2. Performing a left shift twice is the equivalent of multiplying a number by 4.

So, what do does one do when they want to multiply a number by 3? Let’s see:

LDA #64
ROL
ADC #64

In this example, I loaded the number 64 into the accumulator. I used the ROL operation to shift the bits over to the left by 1, essentially multiplying it by 2. The result in the accumulator is now 128. On the third line I added the accumulator (which holds the value 128) to 64 and ended up with the result 192. Remember, 3 multiplied by 64 equals 192!

Let’s try multiplying 4 by 6:

LDA #04
ROL
ROL
ADC #04
ADC #04

In this example, I load the number 4 into the accumulator. I then “roll” or shift the bits over to the left, multiplying them by 4. The accumulator now holds the number 16. I then add 4 to the accumulator twice, ending up with the result 24, which is the result we wanted as 6 multiplied by 4 equals 24!

If you look carefully, trying to perform multiplication on the 6502 is time consuming. I had to perform two left shifts, and add 4 twice to end up with the result 24. I basically multiplied 4 by 2 twice, then added 4, and added 4 again: 4*2*2+4+4.  Yikes!  That’s ugly. To perform the same operation in C you would do the following:

int x = 4;
x = x*6;

In the above example, I assigned 4 to the variable x, then multiplied x by 6, and assigned the result to x. The variable x now holds the number 24! As you can see, the difference between assembly language on the 6502 and traditional programming languages is that you have to cleverly devise ways around your limitations. The 6502 has a lot of limitations like these that the programmer must work around. Today, you can search the Internet for tricks around limitations on obsolete hardware such as the 6502 processor.

If you’re a game designer looking to improve his or her skills, it’s worth learning 6502 assembly, even if you don’t plan to use it. Books on 6502 are free and can be downloaded almost anywhere on the Internet in PDF format. If the 6502 isn’t your cup of tea, you can try more advanced processors such as the 68000 used in the Sega Genesis and classic Macintosh hardware. Learning an old assembly language can really teach you a lot about programming and how hardware works at the lowest level. It may seem frustrating and complicated, but it’s not that bad; just very time consuming.