ASM day 1: I started the "Easy 6502" tutorial
Writing my very first assembly program
Thank you for tuning in, my dear new reader. ^-^
Firstly as a short introduction, I am not a developer by trade. I appreciate the art of writing software a ton, but my only programming experience has been with the nice and easy to use GameMaker. This time however, I’m curious about approaching it from the complete opposite end.
I challenge myself to learn assembly programming
Just for fun! I’ve always wondered about it! It’s like an intimidating puzzle that my brain may or may not be able to grasp. I’m curious if I can do it, and I’d like to take you along for the ride. Even if I don’t get anywhere, I hope my struggles may be interesting to you.
Being fond of the NES and SNES, and also being curious about the PC Engine, deciding on the 6502 family of processors seemed like a sensible enough choice to me.
After expressing my newfound wish, I was soon recommended the Easy 6502 tutorial. It has a built-in miniature 6502 environment, and this is what I’ll be referring to in the next days of getting started. Its rules are described like this:
Memory location
$fe
contains a new random byte on every instruction. Memory location$ff
contains the ASCII code of the last key pressed.Memory locations
$200
to$5ff
map to the screen pixels. Different values ($0-$f
) will draw different color pixels.
What I learned from the first tutorial section
Going in, I know that computer processors know of values, and registers to put these values into. The way the values and registers are manipulated is through instructions written as short mnemonic names in assembly language. Hardware has registers that will act on whatever you put into them, which is super enticing to me when I think of games hardware.
One of the only things I know about the 6502 is that it has an “Accumulator”, which I understood as that feature calculators have where they keep track of the previous answer, which you are then able to use for your next calculation.1
In the first section of the tutorial, “Our first program”, I can see that two instructions are used: LDA
and STA
.
LDA #$01
STA $0200
LDA #$05
STA $0201
LDA #$08
STA $0202
Apparently they stand for LoaD Accumulator and STore Accumulator respectively. Putting a value into a specific register seems to take these two instructions. LDA defines the value and stores it into register A
(I suppose for Accumulator), and STA defines where it is stored. I feel like I remember seeing this done on a single line when looking at other assembly code, so I wonder about that.
I never knew that values (“literal number values”) were written as #$xx
, while $xxxx
portrays a register value.
Playing with my first two instructions
The example program draws three differently colored pixels.
Once I started playing around with the values and got the hang of the screen position and color values, I couldn’t help try to draw something on the black screen. The end result is these blue beams shooting out of laser guns, I guess!
Finally, I noticed this section includes challenges.
Try changing the color of the three pixels.
Done!
Add more instructions to draw extra pixels.
Done!
Change one of the pixels to draw at the bottom-right corner (memory location
$05ff
).Oh, let me do that.
There you go, that’s no trouble for us now! ^-^
And that is all for today. Thank you for reading!
If my understanding is wrong on this or anything else in my posts, then please do not hesitate to correct me by posting a comment.
It's not made clear in the tutorial, but the word "register" can mean a couple of different things.
The universe that the 6502 can see and manipulate are 65536 byte-sized memory locations, numbered $0000 through $FFFF, plus the CPU's own internal registers, like the accumulator ("the A register", and yes, A does stand for Accumulator). The accumulator and other CPU registers don't have memory addresses, they're in a special extra place off to the side (they're in... the CPU rather than in the RAM chips).
However, a CPU alone in a memory space isn't very useful, the computer needs input and output to be useful. Often, these extra devices are wired up to the CPU's memory interface, so that the CPU can access them as though they were memory, but they're not just ordinary RAM chips, they *do* something when you read from or write to them. From the point of view of the connected hardware, these things aren't ordinary memory, they're registers (just like the CPU's accumulator isn't ordinary memory) but from the CPU's point of view they *are* memory, because that's how the CPU accesses them.
In the tutorial's emulated computer, $00FE and $00FF are registers you can read from, and if you squint you might say that $0200..$05FF are registers you can write to, but from the CPU's point of view they're all just memory and very different from the accumulator.
All that to say: it's not quite true to say "values are written as `#$xx` while `$xxxx` portrays a register value". Rather, `$xxxx` means "read from (or write to) memory address `$xxxx`" while `#$xxxx` means "the actual literal value `$xxxx`". It's just that in this specific instance, the accumulator is only 8 bits (so there's no point adding leading zeroes) while the destination location needs more than 8 bits to express (so there's not enough leading zeroes to remove).