我一直在为错误“jmp out of range”而苦苦挣扎,很多时候我需要从我的代码的不同部分运行一个子程序,就像我在 C++ 中运行一个函数一样。
我发现我的代码的两端都需要跳到同一个地方,而两者都无法到达那里。
解决这个问题的方法是什么?
我也注意到PRINT 'something'
似乎比使用占用更多的“空间”:
CALL PTHIS
DB 13, 10, 'something', 0
(如果我在两次跳跃之间放一个 PRINT,我就会跳出范围,但如果我用 PTHIS 替换它,就没有问题)
为什么是这样?
最佳答案
16 位汇编器中条件跳转指令的问题在于它们的偏移量被限制为 +127 或 -128 字节。
386推出jcc rel16
在 16 位模式下可用的编码,但仅适用于 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
是一个普通的(非内联的)函数调用。
关于assembly - 跳出范围解决方案以及不同的指令如何影响范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17307834/