3

我一直在为错误“jmp out of range”而苦苦挣扎,很多时候我需要从我的代码的不同部分运行一个子程序,就像我在 C++ 中的一个函数一样。

我到了一点,我的代码的两端都需要跳转到同一个地方,而且两者都没有办法到达那里。

解决方案是什么?

我也注意到

PRINT 'something'

似乎比使用占用更多的“空间”:

CALL PTHIS
DB 13, 10, 'something', 0

(如果我在两次跳跃之间放了一个 PRINT,我会跳出范围,但如果我用 PTHIS 替换它就没有问题)

为什么是这样?

4

2 回答 2

5

16 位汇编器中的条件跳转指令的问题在于,它们的偏移量被限制为 +127 或 -128 字节。

386 引入了jcc rel1616 位模式下可用的编码,但仅适用于 386 及更高版本。不同的汇编器有不同的选项来启用 16 位代码中的 386 条指令

有些还具有自动执行以下描述的选项:有条件jcc rel8jmp rel16. 例如,TASM 有/jJUMPS.


假设你有这个:

    cmp al, '1'
    jnz ItsNot1
    ; lots of code here
ItsNot1:

如果你得到一个超出范围的错误,你可以像这样重新编码:

    cmp al, '1'
    jz Its1
    jmp ItsNot1
Its1:
    ; lots of code here
ItsNot1:

我所做的只是改变比较的感觉,并绕过将您带到备用代码路径的无条件跳转。

如果您有很多条件跳转,有时会很烦人。您将重新编码其中一个,它会触发另一个。然后你重构代码并发现其中一些被破坏的条件可以消失。通常我不会担心它,除非我非常关心代码大小。

一些汇编程序有一个开关,可以为您自动调整跳转大小,以便您始终可以编写条件跳转代码,它们会自动执行跳转条件跳转技巧。

最有可能的区别

PRINT 'something'

call PTHIS
db 13, 10, 'something'

是不是第一个是一个宏,它扩展为用于打印某些东西的完整代码,以及您要打印的字符串。第二个是简单call指令(3 个字节),加上字符串。或者,在 C++ 术语中,PRINT宏就像一个内联函数,并且call PTHIS是一个普通(非内联)函数调用。

于 2013-06-25T21:37:15.497 回答
0

有时你必须否定你的测试并让分支向前跳跃一点,而跌倒是无条件地跳转到你超出范围的目的地。

于 2013-06-25T21:36:21.767 回答