This lesson will teach you how you can realize absolute and relative jumps and calls.
As you have seen in previous lessons, it is possible to give a name to a certain line of your code. This is called a label
. An example:
In this example, the label mylabel points to the instruction immediately behind it, and this is the INC A instruction. Even more, it actually points to the first byte of the instruction that comes immediately behind it. But since the INC A instruction takes only 1 byte, we don't have to worry about that. And even if the instuction immediately behind the label took more than 1 byte, we would normally not have to worry about that.
As you probably already figured out, we don't place the labels there 'just for fun'. We will do something with them. So what can we do with them?
Well, we can jump to that line using the jp and jr instructions. The Z-80 processor will change the PC (program counter - the register that holds the absolute address of the next instruction that needs to be executed) so it points to the address provided as an operand of the JP or JR instruction.
More details on the difference between JR and JP will follow later in this lesson. Please note that it's not only possible to jump forward, you can also jump backwards!
LD A,$05 ; 1
LD A,$10 ; 2
JP This_Is_A_Label ; 3
LD A,$20 ; 4
LD B,$03 ; 5
This_Is_A_Label: ; 6
LD B,$1A ; 7
Try to figure out what the value of the A and B registers will be at the end of this snipplet of code. A will be $10 and B will be $1A. When this code is executed, the jump on line 3 will make the program counter point to line 7, so the instructions at lines 4 and 5 will never be executed.
Now what's the difference between JP and JR ?
Well JP is an absolute jump and JR is a relative jump. The difference between both is that a relative jump can only jump 128 bytes backwards and 127 forward while the absolute jump (JP) can jump to whatever memory location you desire. On the TI-82 this can be from $0000 to $FFFF.
A question you could ask yourself is: why would you need JR when you can jump anywhere with JP ?
The answer is simple: the JR instruction takes only 2 bytes, where a JP instruction takes 3 (that's in normal circumstances). There is also a difference in execution speed between these two.
To be complete: there are also conditional jumps possible with JP and JR (this means that the jump is only executed if a certain condition has been met). More about these conditional jumps in the lesson 10
When you want to make subroutines that you can call
from inside your program, you'll need the CALL and RET instructions.
What a call does is the following: a jump is made to the address that was given as operand. So far, this looks like a normal jump.
But this time, the address of the instruction that comes immediately after the CALL instruction is stored somewhere in the memory (on the stack - see advanced details further in this lesson). Now, when you are in your subroutine and use RET (return), the processor gets the address back from the memory and jumps to it.
Like with the jumps, you can also use conditional calls and conditional returns. More about that in the lesson 10 and the lesson 11 (handling of keypresses)
; main program
ret ; end of program
Below is some more advanced data on how a call is done, for the people who are interested. You might want to take a look at lesson 12 (the part about the stack) first.
When a call is made, a jump is made to the operand (a memory address) after the address of the instruction immediately behind the call has been pushed onto the stack. When a RET instruction is encountered, the address is popped back from the stack and a jump is made to that address.
This implicates that you'd better make sure that you've popped back everything you pushed on the stack in the subroutine before you return back to the main program. Take a look at the following program and think about what could happen.
This will cause a jump to $8D14 and that's not exactly what we wanted to happen.
Another side note: ever wandered about the fact that we use a RET instruction to end out program? Well, that's simply because Ash and CrASH call the program that needs to be run from inside their code. So actually, you could see your program as a huge subroutine.
Previous lesson |