Z80 绝对跳转到指令中间的偏移量

逆向工程 艾达 嵌入式
2021-06-15 04:48:37

我正在对使用 Z80 处理器的嵌入式系统进行逆向工程。我使用 IDA 作为反汇编程序。我遇到了一个绝对跳转 (JP),它似乎跳转到另一条指令的中间。我未定义并将目标位置重新定义为代码,并将其反汇编为有效指令,但它们似乎没有做任何事情。我想知道我是否可以得到一些帮助来理解这一点,或者我是否忽略了一些东西。

编辑:此跳转是循环的退出点。

源 + Bin + IDB 文件可以在这里找到

跳转代码:

在此处输入图片说明

使用 IDA 自动反汇编跳转目标:

在此处输入图片说明

将121取消定义并重新定义为代码后跳转目标:

在此处输入图片说明

2个回答

没有任何背景,我们只能猜测......

但是jp (hl)通常用于:

  1. 跳转到指针

    这很明显hl指向您要跳转到的内存位置。你可以用它做很多事情,例如你想决定如何处理一些输入,你有更多的处理程序选择,所以你可以评估使用哪个,hl最后直接跳转到它。这同样适用于mode程序的......例如你有渲染文本或某事的更多的方式,你想轻松地对整个方案在两者之间切换...然后简单地存储在某些指针所选择的程序,需要跳转到它时, ...

    我对您的代码没有任何上下文,但这是最有可能的情况:

    286Eh是选定的模式处理程序,使用hl读取该位置ix并最后例行跳转到该位置。我猜决赛ret在某个地方的例行公事中。

  2. 使用非标准调用约定调用/返回到/从子例程

    有时操作数以非标准方式(不在堆栈上)传递给子程序,这会阻止使用callret直接使用在这种情况下jp (hl)可以解决此类问题。

    例如,看看这个 x86 示例:

    printl呼叫之后直接期待打印字符串......

    call printl
    db  'SPEKTRA software & hardware',0
    

    这节省了输入数据指针设置,而且它更舒适,因为打印文本直接使用它(不在数据部分的某些表中),而且您不需要标签。如您所见,printl无法直接返回存储在堆栈中的地址。相反,它需要在文本之后跳转,这是jp (hl)示例的理想用法(但是我的 x86 代码由于不同的指令集而有所不同)。

  3. 解决自修改代码问题

    可配置程序没有静态跳转/调用地址,因此jp (hl)可用于可配置跳转...

现在回到跳到教学中间

这可能是也可能不是。如果您使用反汇编程序,则它不知道ORG每个代码段语句在哪里所以它从文件的开头开始翻译。当您进行跟踪时,它将PC作为起始位置并从中进行相对转换,因此如果您滚动列表,您可能会错误地反汇编代码的其他部分。然而,在几个连续的单字节指令之后,代码再次对齐,因此大部分代码将被正确翻译。

但也有我们故意跳到教学中间的情况。有时,时间敏感的代码需要[T]在某些例程上花费确切数量的节拍,并且在某些指令中间跳转可以解决[T]某些条件行为后丢失的状态。

实际上,JP (HL) 用词不当;它不会跳转到 (HL) 但它会跳转到 HL。代码跳转到 28D3,其中包含一个 21(LD HL,imm),这完全有道理。