为什么在 AT&T 程序集中尝试使用“*...(%rip)”进行 RIP 相对直接跳转时,会得到一个奇怪的长操作码?

dro*_*te7 2 assembly x86-64 gnu-assembler inline-assembly att

问题是我不能强迫gnu as将其解释jmpshortor near,它不断地将其解释为far

例如,以下代码会导致segfault

int main() {
  asm volatile (
//      ".intel_syntax noprefix\n\t"
//      "jmp lbl%=\n\t"
//      "lbl%=:\n\t"
      "jmp *lbl%=(%%rip)\n\t"
      "lbl%=:\n\t"
//      ".att_syntax\n\t"
      : : : );
  return 0;
}

Run Code Online (Sandbox Code Playgroud)

切换到注释的.intel_syntax变体,它工作得很好。

唯一的区别是

jmp lbl%=变成inteleb 00

尽管

jmp *lbl%=(%%rip)变成attff 25 00 00 00 00

.att_syntax如果将其解释为 ,如何强制它short jump

Chr*_*odd 6

jmp *lbl进行间接跳转——从内存中加载地址lbl:并跳转到该地址。在这种情况下,它使用此(函数 Epilog)后面的 8 个(代码)字节并将其视为要跳转到的地址,从而导致段错误。

对于简单的 PC 相对跳转,您只需要jmp lbl-- att 语法与此处的 intel 语法相同。不需要%rip任何东西,因为所有直接跳转都是与 PC 相关的。