x86 32位汇编代码是否有效x86 64位汇编代码?

时间:2017-05-20 17:56:24

标签: windows assembly binary x86

  

所有x86 32位汇编代码是否都有效x86 64位汇编代码?

我想知道32位汇编代码是否是64位汇编代码的子集,即每个32位汇编代码是否可以在64位环境中运行?

我想答案是肯定的,因为64位Windows能够执行32位程序,但后来我发现64位处理器支持32位兼容模式?

如果没有,请提供一个32位汇编代码的小例子,该代码不是有效的64位汇编代码,并解释了64位处理器如何执行32位汇编代码。

2 个答案:

答案 0 :(得分:7)

现代x86 CPU有三种主要的操作模式(简化了这种描述):

  • 实模式下, CPU执行16位代码,禁用分页和分段。代码中的内存地址是指phyiscal地址,段寄存器的内容被移位并添加到地址中以形成有效地址。
  • 保护模式中,CPU根据CS(代码段)寄存器中的段选择器执行16位或32位代码。启用分段,可以(通常是)启用分页。程序可以在16位和32位代码之间切换到适当的段。 CPU可以进入子模式虚拟8086模式,以模拟来自受保护模式操作系统内的各个进程的实模式
  • 长模式下, CPU执行64位代码。分段大多禁用,启用分页。 CPU可以进入子模式兼容模式,从为长模式写入的操作系统中执行16位和32位保护模式代码。 兼容模式<通过远程跳转到具有相应位设置的CS选择器进入/ em>。 虚拟8086模式不可用。

现在16位,32位和64位模式有什么区别?

16位和32位模式基本相同,只是存在以下差异:

  • 在16位模式下,默认地址和操作数宽度为16位。您可以使用0x67和0x66前缀将这些更改为32位。在32位模式下,它是相反的。
  • 在16位模式下,指令指针被截断为16位,跳转到高于65536的地址会导致奇怪的结果。
  • AVX和任何VEX编码指令在16位模式下不可用。
  • 16位模式比32位模式具有更少的寻址模式,但如果需要,可以切换到32位寻址模式。

现在,64位模式有所不同。大多数指令的行为与32位模式类似,但有以下区别:

  • 另外还有8个名为r8,r9,...,r15的寄存器。每个寄存器可用作字节,字,双字或qword寄存器。 REX前缀族(0x40到0x4f)编码操作数是指旧的还是新的寄存器。另外还有8个寄存器SSE寄存器xmm8,xmm9,...,xmm15。
  • 你只能推送/弹出64位和16位数量(虽然你不应该这样做),但是无法推送32位数量。
  • 单字节incdec指令不可用,其指令空间已重新用于REX前缀。双字节incdec仍然可用,因此仍可以对inc regdec reg进行编码。
  • 存在新的指令指针相对寻址模式。
  • 默认地址宽度为64位,可以通过0x67前缀选择32位地址宽度。 16位寻址不可用。
  • 默认操作数宽度为32位。可以通过0x66前缀选择16位宽度,可以通过适当的REX前缀选择64位宽度,与您使用的寄存器无关。
  • 在需要REX前缀的指令中不能使用AH,BH,CH和DH。
  • 写入64位寄存器的低位会清除高位32位。
  • 由于分段不起作用,除了用于支持线程局部存储(TLS)的fsgs覆盖(0x64,0x65)之外,段覆盖不可用。
  • 此外,许多专门处理细分的指令都不可用。它们是:push/pop segpush/pop fs/gs除外),arplcall far(只有0xff编码有效),leslds,{ {1}}(只有0xff编码有效),
  • 处理十进制算术的说明不可用,它们是:jmp fardaadasaaaaasaam
  • 此外,以下说明不可用:aad(很少使用),bound / pusha(对附加寄存器无用),popa(未记录),
  • 0x80的0x82指令别名无效。
  • 在早期的amd64 CPU上,salclahf不可用。

基本上就是这一切!

答案 1 :(得分:5)

不,虽然存在大量重叠,但64位汇编代码不是32位汇编代码的超集,因此32位汇编在64位模式下通常无效。

这适用于助记符程序集 source (由汇编程序组装成二进制格式),以及二进制机器代码格式本身。

This question涵盖了已删除的一些详细说明,但也有许多编码形式的含义已更改。

例如,注释中的Jester给出了push eax在64位代码中无效的示例。基于this reference,您可以看到32位推送标记为 N.E。,意味着不可编码。在64位模式下,编码用于表示push rax(8字节推送)。因此,相同的字节序列在32位模式与64位模式下具有不同的含义。

通常,您可以浏览该站点上的指令列表,并找到许多列为64位无效或无法编码的内容。

  

如果没有,请提供一个32位汇编代码的小例子   是无效的64位汇编代码并解释64位处理器如何   执行32位汇编代码。

如上所述,push eax就是这样一个例子。我认为缺少的是64位CPU支持直接运行32位二进制文​​件。它们不是通过机器语言级别的32位和64位指令之间的兼容性来实现的,而只是通过具有 32位模式,其中解码器(特别是)解释指令流作为32位x86而不是x86-64,以及用于运行64位指令的所谓长模式。当这样的64位芯片首次发布时,通常运行一个32位操作系统,这意味着芯片永远处于这种模式(永远不会进入64位模式)。

最近,通常运行一个64位操作系统,它知道模式,当用户启动32位进程时,它会使CPU进入32位模式(这仍然是非常的常见的是:直到最近我的浏览器仍然是32位。

模式的所有细节和正确术语都可以在fuz的答案中找到,这是你应该阅读的答案。