条件跳转到内存地址
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
。或者它是如何工作的?
似乎这里至少发生了一些事情,但其中之一是:
- 发出警告,除非我将
jmp %r11
更改为 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
你的方法的优点是在“不相等”的情况下不进行跳转,尽管现代处理器上的分支预测不应该在“采用”和“不采用”之间留下太大差异。我的方法的优点是两种情况都不涉及两次跳转,并且不会跳转到缓存中可能冷的某个相对较远的中间地址。
注意区别:
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
到 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:
通常最好有条件地跳转到或越过间接 jmp
或 ret
以提早退出 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)
可能是下面这样的吗?
cmp , %rdi
jz (%r11)
file.s:52: Error: operand type mismatch for `jz'
或:
Warning: indirect jmp without `*'
或者您是否必须跳转 'through' 一个标签,然后才能执行 jmp %r11
。或者它是如何工作的?
似乎这里至少发生了一些事情,但其中之一是:
- 发出警告,除非我将
jmp %r11
更改为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
你的方法的优点是在“不相等”的情况下不进行跳转,尽管现代处理器上的分支预测不应该在“采用”和“不采用”之间留下太大差异。我的方法的优点是两种情况都不涉及两次跳转,并且不会跳转到缓存中可能冷的某个相对较远的中间地址。
注意区别:
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
到 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:
通常最好有条件地跳转到或越过间接 jmp
或 ret
以提早退出 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)