如何解决条件跳转到内存地址
是否可能出现以下情况?
cmp $3,%rdi
jz (%r11)
file.s:52: 错误:`jz' 的操作数类型不匹配
或者:
警告:没有`*'的间接jmp
或者您是否必须“跳过”一个标签,然后才能执行 jmp %r11
。或者它是如何工作的?
这里似乎至少发生了一些事情,但其中之一是:
- 发出警告,除非我将
jmp %r11
更改为jmp *%r11
(为什么?)
目前我正在做的是回旋处:
cmp $3,%rdi
jz fast_ret
fast_ret:
jmp *%r11
解决方法
不,all the conditional jump instructions on x86 are immediate;它们将目标地址直接编码到指令中(作为跳转指令本身地址的位移)。你不能有条件地从寄存器或内存位置跳转到一个地址。
你可以做你所做的,并跳转到所需的跳转指令。或者,您可以反向测试并跳过您真正想要的寄存器或间接跳转。
cmp $3,%rdi
jnz dont_go
jmp *%r11
dont_go:
// rest of your program
您的方式的优点是在“不相等”的情况下不进行跳转,尽管现代处理器上的分支预测不应在“已采用”和“未采用”之间留下太大区别。我的方法的优点是,两种情况都不需要进行两次跳转,并且不会跳转到缓存中可能很冷的某个相对较远的中间地址。
注意以下区别:
-
jmp %r11
:AT&T 的无效语法,绝对跳转总是使用*
前缀,参见 https://sourceware.org/binutils/docs/as/i386_002dVariations.html#i386_002dVariations。 -
jmp *%r11
:使用%r11
的内容作为跳转的地址。您可以将其视为执行mov %r11,%rip
。 -
jmp *(%r11)
:间接跳转,从%r11
包含的地址中取出目的地址。您可以将其视为执行mov (%r11),%rip
。
不,不是,汇编语言只能做机器代码允许的事情,请参阅 https://www.felixcloutier.com/x86/jcc 并注意它们都是 jcc rel8/rel32
相对直接的,而不是间接的。
您可以 cmov
在 jmp *%reg
的地址之间进行选择,这样它就可以使用以下内容跳转到下一条指令:
# possible,but not recommended
# %r11 holds a target address you might want to jump to
lea .Lfallthrough(%rip),%r10
cmp ...
cmovne %r11,%r10 # make the jump go to R11 if !=
jmp *%r10
.Lfallthrough:
通常最好有条件地跳转到或跳过间接 jmp
或 ret
以获得提前退出的 ret
,或者有条件的间接跳转,如果你不能轻易地通过一个间接分支目标的可能性。
如果间接分支预测器没有目标地址预测,则默认为下一条指令,因为可以构造这样的情况,其中存在一种实际可能性。
给出警告,除非我将 jmp %r11 更改为 jmp *%r11(为什么?)
因为这就是 AT&T 语法的工作原理。 https://sourceware.org/binutils/docs/as/i386_002dVariations.html - AT&T 绝对(相对于 PC 相对)跳转/调用操作数以 *
这对于消除裸内存操作数的歧义是必要的,并且为了一致性,所有间接跳转/调用都需要装饰。
-
jmp foobar
(跳转到那个符号,设置 EIP/RIP=foobar
) -
jmp *foobar
(从符号foobar
的绝对地址加载一个指针到 EIP/RIP)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。