Jump anywhere: Difference between revisions

m
m (→‎Jumping to a Variable Location: Added an example use case for JP (HL))
Line 2,866:
The incredibly misleading <code>JP (HL)</code> will copy the value in the <code>HL</code> register pair directly to the program counter. You would think based on the parentheses that it looks up the value stored at the memory location in <code>HL</code>, but it doesn't! This is the fastest jump command the Z80 has.
 
<code>JP (HL)</code> can be used to create a "trampoline," which lets you indirectly call a subroutine, provided that subroutine doesn't take <code>HL</code> as an argument. (Otherwise you'll get some unwanted results.) To do this, you need to know the address of the subroutine you wish to call, load it into HL, then <code>CALL</code> any address that contains either <code>JP (HL)</code> or the byte 0xE9. (<code>JP (HL)</code>'s bytecode is 0xE9). Once you do this, execution will effectively "call the address that contains the 0xE9, and interpret that as <code>JP (HL)</code>, taking you to" the desired routine. For this to work, the desired routine must end in a <code>RET</code>, and balance the stack properly. That way, when it does <code>RET</code>, it will <code>RET</code> to where you were just after the <code>CALL</code>.
 
<lang z80>
ld hl,foo ;rather than directly specifying "foo", you would normally retrieve it by indexing a table.
ld hl,foo
;This was done only to keep the example as simple as possible.
;If you're going to load it as a constant into HL you're better off just CALLing it outright.
call Trampoline
;execution will return here, with HL = address of "foo" and A = 0.
1,489

edits