我一直在努力解决“jmp超出范围”的错误,很多时候我需要从我的代码的不同部分运行一个subrutine,就像我在C ++中的函数一样。
我得到的一点是,我的代码的两端都需要跳到同一个地方,两者都没办法到达那里。
这是什么解决方案?
我也注意到了
PRINT 'something'
似乎比使用更多“空间”:
CALL PTHIS
DB 13, 10, 'something', 0
(如果我在两次跳跃之间放置PRINT,我会跳出范围,但如果我用PTHIS替换它就没有问题)
为什么会这样?
答案 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)
有时候你必须否定你的测试并让分支稍微超前一点,而跌倒是无条件跳转到你的超出目的地。