我想得到这些命令:
jl some_label(%rip)
# or
jl *%rax
在我为英特尔x64架构编写的asm程序中。
当我尝试编译这段代码时,GCC说“jl的操作数类型不匹配”。
条件跳转在x86上是相对的。您可以使用“反向”条件跳转,然后是无条件跳转:
jge skip_jump
jmp *%rax # AT&T syntax
skip_jump:
等效的NASM语法是jmp rax
。无论哪种方式,它设置RIP = RAX,因此它是寄存器间接跳转。
有条不紊地跳过间接的jmp rax
通常是要走的路。
另一个选择是使用cmov
修改目标地址:
## Normally worse than jge, but worth considering
lea stay_here(%rip), %rdx # pick any register
cmovge %rdx, %rax
jmp *%rax
stay_here:
这是更大的代码大小和更多uops,但在所采用的路径上只有一个总分支。此外,如果BTB没有历史记录,则间接分支目标的默认预测通常是+0
(即下一条指令),因此在预测变量为冷的情况下可以正确预测。
除此之外,跳转到下一条指令不是特殊的,仍然需要正确的预测,并且仍然可能减慢前端的速度。
在一些具有简单/弱间接分支预测的CPU上,将条件合并到间接分支几乎肯定会受到影响,因为它是一个额外可能的分支目标。
但是如果你发现jge
/ jmp
组合并不能很好地预测,那么将其作为一种混合方式是值得尝试的。