x86和x86-64机器代码的差异

时间:2014-11-22 17:36:57

标签: assembly x86 x86-64 jit machine-code

所以,我有一个生成JIT x86机器代码的程序并直接执行它,我希望它也支持x86-64 / AMD64 / x64。明显的区别是:

  • 新寄存器(raxr8 ...)和指针宽度(指针需要使用64位寄存器)
  • 默认C调用约定(堆栈与寄存器上的参数)
  • 一些新的助记符(pushq推64位)

二进制指令是否有任何差异,或者在适当时使用pushq和64位寄存器(大致)是否足够,并且代码才有效?

代码示例:

static inline void emit_call(uint32_t target) {
    emit_byte(0xE8);
    emit_dword(target - ((uint32_t)out + 4));
}

如果我使用uintptr_t代替uint32_t,我仍然会这样做,我认为, 但是将一个立即数加载到64位寄存器rax与将其加载到较低的32位别名不同:

static void emit_mov_x86reg_immediate(int x86reg, int imm) {
    emit_byte(0xB8 | x86reg);
    emit_dword(imm);
}

还有其他差异吗?

我正在处理的代码here是可访问的,如果您想查看它。

1 个答案:

答案 0 :(得分:3)

旧的32位推送和新的64位推送之间实际上没有区别,这是隐式 64位的少数指令之一。

相对分支和呼叫仍然使用32位偏移。

一些实际差异是:

    显然,
  • REX前缀用于额外的寄存器(还记得sildil - 没有设置位的REX前缀仍然很重要!)
  • 再次
  • REX前缀,它曾是40+rd48+rd的短编码(incdec)。因此incdec必须是FF /1编码。
  • rip - 相对地址
  • 64位立即加载,mov使用直接64位地址
  • sign-extend 32bit to 64bit(movsxd)与arpl共享操作码
  • leslds不存在,重新用作VEX前缀(在32位模式下,只有leslds非法操作数是VEX前缀,这就是为什么VEX前缀的编码有点奇怪)
  • 删除了几个没有人在64位模式下使用或无用的旧指令(十进制数学,boundintopushadpop es和朋友)< / LI>
  • 82 /?的{​​{1}}别名不再有效
  • 某些旧的x64处理器上不存在
  • 80 /?lahf(不是你还是使用它们。)