.relocate address
Defines a block of code as relocatable. Whilst the block of code is output at the current address, all labels are calculated with an offset applied, to allow the block of code to be copied elsewhere with the correct label addresses.
Here is a stupid example. We are running on a ROM, but we have some RAM at location $C000. We have a routine that relies on self-modifying code. We need to copy it into RAM, therefore to run it. The routine is between the labels code and code_end.
ram = $C000 ; RAM is at location $C000 .org $0000 ; We're in ROM. ; Copy to RAM ld hl,code ld bc,code-code_end ld de,ram ldir ; Run it: call ram ; End the program di halt ; --- code .relocate ram ld a,10 ld (counter+1),a loop call do_something counter ld a,0 ; Self-modifying dec a ld (counter+1),a jp nz,loop ret .endrelocate code_end ; --- do_something push af out ($CC),a pop af ret
The jump to loop will work fine, as the label is inside the relocated code block. The routine do_something is called using the absolute address, as it is defined outside of the relocated code block.
Bear in mind that the special symbol $ (current instruction pointer) is also translated.