跳出范围解决方案以及不同指令如何影响范围

时间:2013-06-25 21:25:52

标签: assembly x86-16

我一直在努力解决“jmp超出范围”的错误,很多时候我需要从我的代码的不同部分运行一个subrutine,就像我在C ++中的函数一样。

我得到的一点是,我的代码的两端都需要跳到同一个地方,两者都没办法到达那里。

这是什么解决方案?

我也注意到了

PRINT 'something'

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

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

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

为什么会这样?

2 个答案:

答案 0 :(得分:5)

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

386引入了16位模式下可用的jcc rel16编码,但仅限于386及更高版本。不同的汇编程序有不同的选项可以在16位代码中启用386条指令

有些人还可以选择自动执行下面描述的操作:条件jcc rel8超过jmp rel16。例如,TASM has /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是正常(非内联)函数调用。

答案 1 :(得分:0)

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