跳出范围解决方案以及不同的指令如何影响范围 [英] Jump out of range solutions and how different instructions affect range

查看:170
本文介绍了跳出范围解决方案以及不同的指令如何影响范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在为错误"jmp超出范围"而苦苦挣扎,很多时候,我需要从代码的不同部分运行子例程,就像在C ++中运行函数一样.

我到了一个地步,我的代码的两端都需要跳到相同的地方,而且都没有办法到达那儿.

对此有什么解决方案?

我也注意到了

PRINT 'something'

似乎比使用以下方法会占据更多的空间":

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

(如果我将PRINT放在两次跳跃之间,我会跳出范围,但如果我将其替换为PTHIS,则没有问题)

这是为什么?

解决方案

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

386引入了jcc rel16编码,该编码在16位模式下可用,但仅在386及更高版本上可用.不同的汇编器具有不同的选项,可以启用16位代码中的386条指令

有些人还具有自动执行以下描述的选项:在jmp rel16上有条件的jcc rel8.例如, TASM具有/jJUMPS ./p>


假设您有这个:

    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是一个普通的(非内联)函数调用.

I've been struggling a lot with the error "jmp out of range", a lot of times I need to run a subrutine from different parts of my code as I would a function in C++.

I got to a point that both ends on my code need to jump to the same place and there is just no way for both to get there.

What is the solution for this?

Also I noticed that

PRINT 'something'

Seems to occupy more "space" than using:

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

(If I put a PRINT between two jumps I get jump out of range but if I replace it with a PTHIS there is no problem)

Why is this?

解决方案

The problem with the conditional jump instructions in 16-bit assembler is that they're limited to +127 or -128 bytes for the offset.

386 introduced the jcc rel16 encoding that is available in 16-bit mode, but only on 386 and later. Different assemblers have different options for enabling 386 instructions in 16-bit code

Some also have options to automatically do what's described below: conditional jcc rel8 over a jmp rel16. For example, TASM has /jJUMPS.


Let's say you have this:

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

If you get a jump out of range error you can re-code it like this:

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

All I did there is change the sense of the comparison and jump around the unconditional jump that takes you to the alternate code path.

It gets annoying sometimes if you have lots of conditional jumps. You'll re-code one of those and it'll trigger another. And then you refactor the code and discover some of those mangled conditionals can go away. Typically I don't worry about it unless I'm seriously concerned about code size.

Some assemblers have a switch that will do automatic jump sizing for you so that you can always code the conditional jumps and they'll do the jump-around-conditional-jump trick automatically.

Most likely the difference between

PRINT 'something'

and

call PTHIS
db 13, 10, 'something'

Is that the first one is a macro that expands to the full code for printing something, plus the string you want to print. The second is a simple call instruction (3 bytes), plus the string. Or, in C++ terms, the PRINT macro is like an inline function, and the call PTHIS is a normal (not inlined) function call.

这篇关于跳出范围解决方案以及不同的指令如何影响范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆