条件跳转到内存地址

Conditional jump to memory address

可能是下面这样的吗?

cmp , %rdi
jz (%r11)

file.s:52: Error: operand type mismatch for `jz'

或:

Warning: indirect jmp without `*'

或者您是否必须跳转 'through' 一个标签,然后才能执行 jmp %r11。或者它是如何工作的?

似乎这里至少发生了一些事情,但其中之一是:

目前我正在做的是环岛:

cmp , %rdi
jz fast_ret

fast_ret:
    jmp *%r11

没有,all the conditional jump instructions on x86 are immediate;他们将目标地址直接编码到指令中(作为跳转指令本身地址的位移)。您不能有条件地从寄存器或内存位置跳转到地址。

你可以做你做的,跳转到你想要的跳转指令。或者你可以逆向测试并绕着你真正想要的寄存器跳转或间接跳转。

    cmp , %rdi
    jnz dont_go
    jmp *%r11
dont_go:
    // rest of your program

你的方法的优点是在“不相等”的情况下不进行跳转,尽管现代处理器上的分支预测不应该在“采用”和“不采用”之间留下太大差异。我的方法的优点是两种情况都不涉及两次跳转,并且不会跳转到缓存中可能冷的某个相对较远的中间地址。

注意区别:

不,它不是,汇编语言只能做机器代码允许的事情,请参阅 https://www.felixcloutier.com/x86/jcc 并注意它们都是 jcc rel8/rel32 相对直接的,而不是间接的。

可以 cmov 到 select 之间的地址 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:

通常最好有条件地跳转到或越过间接 jmpret 以提早退出 ret 或有条件的间接跳转,如果您不能轻易做到fallthrough 您的间接分支目标可能性之一。

如果间接分支预测器没有目标地址预测,则默认为下一条指令,因为有可能构建这样的情况,其中存在一种实际可能性。


Giving a warning unless I change jmp %r11 to jmp *%r11 (why?)

因为这就是 AT&T 语法的工作原理。 https://sourceware.org/binutils/docs/as/i386_002dVariations.html - AT&T 绝对(相对于 PC 相对)jump/call 操作数以 *

为前缀

这对于消除裸内存操作数的歧义是必要的,并且为了保持一致性,所有间接跳转/调用都需要装饰。

  • jmp foobar(跳转到那个符号,设置EIP/RIP=foobar
  • jmp *foobar(从符号 foobar 的绝对地址加载指针到 EIP/RIP)