【问题标题】:Conditional jump to memory address有条件跳转到内存地址
【发布时间】:2021-06-21 19:27:24
【问题描述】:

是否可能出现以下情况?

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

【问题讨论】:

    标签: assembly x86 x86-64 gnu-assembler


    【解决方案1】:

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

    你可以做你所做的,并跳转到所需的跳转指令。或者您可以反转测试并绕过您真正想要的寄存器或间接跳转。

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

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

    注意以下之间的区别:

    【讨论】:

      【解决方案2】:

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

      可以 cmovjmp *%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,或有条件的间接跳转,如果你不能轻易地通过你的间接分支目标之一可能性。

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


      除非我将 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的指针)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-20
        • 1970-01-01
        • 1970-01-01
        • 2023-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多