An Easy 6502 screen with a short listing, showing the pixels on the right.
OUR EXPERT
David Bolton used to write Commodore 64 games for a living back in the mists of time, and taught himself Z80 by writing a 6502 assembler in Z80.
OUR EXPERT
David Bolton used to write Commodore 64 games for a living back in the mists of time, and taught himself Z80 by writing a 6502 assembler in Z80.
How long do you think it took to modify a 2,200-line C program that runs on Windows H to have it run on Linux? Just one hour. The main changes were switching some string routines such as strcpy_s to strncpy, altering paths for includes and changing the high-speed timing code. It might take between a week and a month or longer to do that in assembly. And moving that C code from, say, Ubuntu on x86 to Raspberry Pi on ARM would take almost no time at all. In assembler, it would take a complete rewrite; more months of work.
Having tried to put you off modern assembly, let’s try some old-fashioned assembler from 40 years ago. With roughly 60 instructions, the 6502 CPU is simpler than modern CPUs, which can have several hundred.
What is a 6502?
Pretend it’s 1983 and you have bought a brand new Commodore 64 and assembler cartridge that will ‘compile’ 6502 assembler into machine code. In this article, we are learning some 6502 assembly language, writing a short program in it and then running it on a web emulator.
The 6502 has just three registers: A (known as the accumulator), X and Y. Each register is 8-bit, so can hold a number between 0 and 255. It’s easier to deal with values and addresses in base 16 – hexadecimal – so a byte holds a value between $00 and $FF.
You can find a list of all the 6502 instructions and details about addressing modes and lots more at www. masswerk.at/6502/6502_instruction_set.html, but here are a few useful things you should know about the Commodore 64 and the 6502 CPU.
On the Commodore 64, the processor is actually a 6510 (a 6502 with a bit of hardware mapped in). It has 6,553610 bytes of RAM, but some RAM addresses are used for the hardware sprites. In hexadecimal, 6,553610 is $10000 and the memory addresses run from $0000-$FFFF. However, the Commodore 64 charset graphics are mapped at $1000-$2000, sprite hardware is mapped at addresses D000-D02E, the sound hardware at D400-D7FF, parallel port at DC00-DCFF, and so on. So, your program should use RAM in the region between $2000 and $CFFF, which is 45,055 bytes – enough for most games. And, of course, page zero, which is the first 256 bytes, and runs from $00-$FF. By putting variables and data in page zero, the instructions to access them are only two bytes long – the opcode is the first byte and the address is the second byte. Accessing memory in addresses after page zero is slower because it requires two byte addresses and those instructions are three bytes long.
An Easy 6502 results window after a successful assemble.
Machine code, assemble!