assembly 为什么在AT&T汇编中使用'*...(%rip)'进行RIP相关直接跳转时,会得到一个很长的操作码?

y3bcpkx1  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(188)

问题是我不能强迫gnu asjmp解释为shortnear,它总是将其解释为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;
}

切换到注解的.intel_syntax变体,它工作得非常好。
唯一的区别是
intel中的jmp lbl%=变为eb 00

att中的jmp *lbl%=(%%rip)变为ff 25 00 00 00 00
如果是.att_syntax,如何强制将其解释为short jump

lvmkulzt

lvmkulzt1#

jmp *lbl执行一个 * 间接 * 跳转--从lbl:的内存加载地址并跳转到该地址。在这种情况下,它获取此函数(函数epilog)之后的8个(代码)字节,并将其视为要跳转到的地址,从而导致segfault。
对于一个简单的PC相对跳转,你只需要jmp lbl-- att语法和intel语法一样,不需要%rip,因为所有的直接跳转都是相对于PC的。

相关问题