Code rarely goes in a straightforward motion. Actually to do something useful we must teach the code how to jump to the correct parts, to stop when it needs to, to call subroutines... Before seeing Jumps we need to know about three processor registers:
The Program Counter (PC) is a 16-bit register containing the address of the instruction the processor will read next.
When the current instruction is read, the processor calculates (based on the current opcode and the operands it believes come next) the address of the following instruction. When the cpu finishes processing the current instruction then it will use the value in the program counter to continue the operation.
The Stack Pointer (SP) is an 8-bit register containing an index which points to the current top of a data structure called the stack.
The stack, on the 6510 cpu, is an area of memory reserved for keeping return addresses for subroutines, in case you need to make nested function calls. You can push data on the stack, and then get it back from it, or pop it, with a last-in-first-out precedence rule. The Stack Pointer only needs 8 bits, because it’s a fixed section of memory starting from $0100 and ending with $01FF.
The 6510 cpu reserves a very tiny space for its own stack because programming the 6510 you are expected to store the accumulator, the CPU status register and the CPU program counter. It’s a design choice that is sensible considering the era when it was created (its father, the 6502, was created in 1975) and the scarcity of RAM available for computer programmers. Modern CPUs allow programmers to keep complex data on the stack (function parameters, function results), and each process actually manages its own stack.
Note that the stack is built downwards, so the first value you will push (insert in it) will be in $01FF, the second $01FE.
The Status Register is an 8-bit register containing some flags. Several instructions will set or reset the single bits in the Status Register, and most jump instructions will test those bits to decide if to jump or not. We will see the Status Register more in detail with the next part, when we will talk about conditional jumps.
JMP - Unconditional Jump
JMP LABEL ; here we will use an assembler LABEL.
JMP $0820 ; here we will directly point to a certain address
; in memory.
The unconditional jump resembles the GOTO instruction in basic. You are telling the CPU to set the Program Counter to the operand, either the label or the memory address.
Note that the assembler software calculates the correct memory address for a LABEL automatically. It’s better to use (and abuse) LABELs because if you need to amend your code you don’t need to calculate the memory area, or worse, the number of bytes you need to pass to the operand.
JSR - Jump to Subroutine
Jump to Subroutine is an unconditional jump too, with a key difference from JMP: it’s used together with the RTS (return from subroutine) instruction.
JSR and RTS are conceptually equivalent to the basic GOSUB and RETURN statements.
Technically speaking, JSR will PUSH the current Program Counter on the stack, or better said record the two bytes of the PC on the stack and decrease the value in the SP register by two. RTS instead will POP the PC from the Stack, or better said, increase the value in the SP register by 2 read from the stack the value of the last program counter recorded on it.
RTS ; this RTS halts execution of your program and
; eventually gives the control back to the C64
; operating system
RTS ; this RTS “returns” from the PRINT subroutine
Next time we will see conditional jumps, or branches.