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

lis*_*aro 3 assembly x86-16

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

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

这是什么解决方案?

我也注意到了

PRINT 'something'

似乎占用了比使用更多的"空间":

CALL PTHIS
DB 13, 10, 'something', 0
Run Code Online (Sandbox Code Playgroud)

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

为什么是这样?

Jim*_*hel 5

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

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

有些人还可以选择自动执行下面描述的操作:条件优先jcc rel8于a jmp rel16.例如,TASM有/jJUMPS.


假设你有这个:

    cmp al, '1'
    jnz ItsNot1
    ; lots of code here
ItsNot1:
Run Code Online (Sandbox Code Playgroud)

如果跳出范围错误,可以像这样重新编码:

    cmp al, '1'
    jz Its1
    jmp ItsNot1
Its1:
    ; lots of code here
ItsNot1:
Run Code Online (Sandbox Code Playgroud)

我在那里所做的只是改变了比较的意义,并跳转到无条件跳转,将你带到备用代码路径.

如果你有很多条件跳跃,它有时会很烦人.你将重新编码其中一个,它会触发另一个.然后你重构代码并发现一些受损的条件可能会消失.通常我不担心它,除非我严重关注代码大小.

有些汇编器有一个开关,可以为你做自动跳转大小调整,这样你就可以随时编码条件跳转,并且它们会自动执行跳转条件跳转技巧.

最有可能的区别

PRINT 'something'
Run Code Online (Sandbox Code Playgroud)

call PTHIS
db 13, 10, 'something'
Run Code Online (Sandbox Code Playgroud)

这是第一个是扩展为完整代码以打印内容的宏,以及要打印的字符串.第二个是简单call指令(3个字节),加上字符串.或者,在C++术语中,PRINT宏类似于内联函数,并且call PTHIS是正常(非内联)函数调用.