我想获取这些命令:
jl some_label(%rip)
# or
jl *%rax
我正在为英特尔x64架构编写汇编程序。
当我尝试编译此代码时,GCC会提示“jl操作数类型不匹配”。
在x86上,条件跳转是相对的。您可以使用“倒置”的条件跳转,然后是一个无条件跳转:
jge skip_jump
jmp *%rax # AT&T syntax
skip_jump:
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,但在taken path上只有一个总分支。此外,对于间接分支目标的默认预测通常是+0
(即下一条指令),如果BTB没有其历史记录,则可能在预测冷启动时正确预测。
除此之外,跳转到下一条指令并没有特殊处理,仍然需要正确的预测,并且仍然可能减慢前端速度。
在某些具有简单/弱间接分支预测的CPU上,将条件合并到间接分支中几乎肯定会造成损失,因为它是一个额外的可能分支目标。
但是,如果您发现jge
/ jmp
组合的预测效果不佳,这将是值得尝试的一种混合方法。
jmp %rax
指令的大小为4个字节,则jge skip_jump
将简单地变成7D 04
(或者按最低有效位先写的04 7D
)。 - Michael