I'm working on reverse engineering an embedded system which uses a Z80 processor. I'm using IDA as the disassembler. I ran upon an absolute jump (JP) that seems to jump to the middle of another instruction. I undefined and redefined the target location as code, and it disassembled into valid instructions, but they don't appear to do anything. I was wondering if I could get some help making sense of this or if I'm overlooking something.

Edit: This jump is an exit point for a loop.

Source + Bin + IDB file can be found here

Jump code:

enter image description here

Jump target with IDA auto disassembly:

enter image description here

Jump target after undefining and redefining 121 as code:

enter image description here

  • 1
    Hi and welcome to RE.SE. Please post the relevant code as actual text. This will ensure that it can be searched. Images are hard to search for keywords. Thanks.
    – 0xC0000022L
    Commented Jan 14, 2019 at 9:50

2 Answers 2


without any context we can only guess...

However jp (hl) was commonly used for:

  1. jump to pointer

    this one is obvious hl points to a memory location that you want to jump to. You can do many things with this like for example you want to decide how to handle some input and you got more choices of handlers so you evaluate which to use in hl and at the end just jump to it. The same goes for mode of a program... For example you got more ways of rendering text or something and you want easily switch between them for the whole program ... then simply store the selected routine in some pointer and when needed jump to it...

    I do not have any context to your code but this is the most likely scenario:

    286Eh is the selected mode handler, hl read that position using ix and lastly routine jump to it. I am guessing the final ret is in the routine somewhere.

  2. call/return to/from subroutine with non standard calling convention

    sometimes operands are passed to subroutines in non standard ways (not on stack) which prevent to use call or ret directly. In such cases jp (hl) can solve such issues.

    For example take a look at this x86 example:

    the printl is expecting printed string directly after the call ...

    call printl
    db  'SPEKTRA software & hardware',0

    this spares the input data pointer setting and also its more comfortable as the printed text is directly where it is used (not in some table in data section) also you do not need labels. As you can see the printl can not ret directly to the address stored in stack. Instead it needs to jump after the text which is ideal usage of jp (hl) example (however my x86 code does it differently due to different instruction set).

  3. resolve self modify code issues

    configurable programs do not have static jump/call addresses so jp (hl) can be used for configurable jumps...

Now getting back to jumping into middle of instruction

This might be or might not be true. If you use disassembler then it does not know where the ORG statement of each code segment is. So it instead translates from start of the file. When you are tracing then it takes the PC as the starting position and translates from it relatively so if you scroll the listing you might got wrongly disassembled other parts of code. However after few continuous single byte instructions the code is aligned again so most of the code would be translated correctly.

But there are also cases when we deliberately jump to middle of instruction. Sometimes time sensitive code needs exact number of [T] tacts to spend on some routine and jumping in the middle of some instruction can resolve missing [T] states after some conditional behavior.

  • In this case it is a #2 scenario, the jump is within a subroutine with no return instruction. I should have explained better in the original post, but 28e6 contains a memory address, which contains another memory address, which resolves to 0121h. 0121h is the jump target and is in the middle of another instruction. I attached the code and IDB file above for context.
    – Zman37
    Commented Jan 14, 2019 at 22:06
  • @Zman37 I do not have Z80 disassembler other than my own emulator and too lazy to convert it to one. Anyway by context I mean what is the device for, what is the architecture, what memory location is ROM and RAM? As I mentioned its high likely the code should start at 121h instead of 11Fh which could be just cause of the linear translation from known start so the last listing is valid. Anyway you might also overlook self modification if the 28E6 and or 28D3 is in RAM and your listing is not tracing self modification changes (I do not know IDA) so the jump address might be different
    – Spektre
    Commented Jan 15, 2019 at 8:25
  • @Zman37 the wrong start of code is usually caused by data sections between routines (disassembler can not distinct which BYTES are data and which instructions unless executed at least once) sometimes ORG directive is used so the routines and or data is at specific location and or align either to enable simpler math or due to HW relation ...
    – Spektre
    Commented Jan 15, 2019 at 8:28

Actually, JP (HL) is a misnomer; it doesn't jump to (HL) but it jumps to HL. The code jumps to 28D3, which contains a 21 (LD HL, imm), which makes complete sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.