In this installment, we’re going to continue to learn more about the three primary registers in the 6502 processor (accumulator, X, and Y). We’ll also create our first simple subroutine.

You can [Download not found] for this program.


Before we do anything else, let’s take a moment to talk about comments. Comments are text in your source code that are human-readable, intended to help you remember what your code is doing (and so others can read your code more easily).

There are two formats for comments. Comments starting with a semicolon (“;”) can be placed stand-alone on a line of code, or can be at the end of any line of code. Comments starting with an asterisk (“*”) can only be placed on a line by themselves. In both cases, the comment extends from the character that starts the comment to the end of the line.

We’ve been using these already, but it just occurred to me that I haven’t actually talked about them yet, so there you go.

Our First Subroutine

Let’s start by creating our first subroutine. This simple routine just takes the value in the X register and prints it to the screen, followed by a carriage return. We’ve used the PRBYTE and CROUT firmware routines in the past, so we won’t dwell on them.

Let’s look at the code:

* xcr
* Prints the byte in X then a carriage return.
xcr      start
         txa                            ;Copy X to A
         jsr   PRBYTE                   ;Print the byte in A
         jsr   CROUT                    ;Print CR
         rts                            ;Return to caller

The first thing this code does is use the implied mode instruction TXA (Transfer X register to Accumulator) to copy the value in the X register into (believe it or not) the accumulator. We do this because the PRBYTE firmware routine prints the value in the accumulator, but we want to use the X register in this case.

Then we call CROUT to output a carriage return, and use RTS to return to the caller.

Incrementing and Decrementing

A very common operation is the need to add or subtract one from a number. For this reason, the 6502 has special instructions just for that purpose. This time, we’re going to look specifically at incrementing and decrementing the index registers.

The INX (INcrement X register) and INY (INcrement Y register) instructions add one to the value of the respective registers. Similarly, DEX (DEcrement X register) and DEY (DEcrement Y register) subtract one from these registers.

Let’s take a look at a code sample:

* Demo increment and decrement

         ldx   #$00                     ;Start with zero
         jsr   xcr                      ;Print it
         inx                            ;Increment X
         jsr   xcr                      ;Print it
         dex                            ;Decrement X
         jsr   xcr                      ;Print it
         dex                            ;Oooh, now what?
         jsr   xcr                      ;Print that

We start by setting the X register to zero and calling our xcr routine to print that value to the screen.

Then we increment X and print the resulting value (in this case, $01).

Then we decrement X and print the result again (this time, $00).

Now, let’s see what happens when you decrement the X register again. The result is $FF (255). That’s right, they wrap around. if you then incremented X again, the result would wrap back to $00.

This is called carry, and it’s similar to what you do when you’re doing addition and subtraction by hand. You have to carry the result from one column to the next when adding or subtracting by hand; similarly, when doing math byte by byte, you have to carry the result from one byte to the next.

We’ll be looking in more detail as to how the carry bit works and how to perform multi-byte mathematics later.

Next Time

Next time, we’re going to apply this knowledge about incrementing and decrementing values to build our first loop to repeat an operation several times until the desired result is achieved.