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

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

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

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

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

Solutions Collecting From Web of "x86 32位汇编代码是否有效x86 64位汇编代码?"

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

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

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

16位和32位模式基本上是相同的,除了以下的区别:

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

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

  • 还有八个名为r8,r9,…,r15的附加寄存器。 每个寄存器都可以用作字节,字,双字或qword寄存器。 REX前缀(0x40到0x4f)族编码操作数是指旧的还是新的寄存器。 八个附加寄存器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 seg (除了push/pop fs/gs ), arplarpl call far (只有0xff编码有效), lesldsjmp far (只有0xff编码有效),
  • 处理十进制算术的指令是不可用的,它们是: daadasaaaaasaamaad
  • 此外,以下指令不可用: bound (很少使用), pusha / popa (对于其他寄存器salc ), salc (无证)
  • 0x80的0x82指令别名无效。
  • 在早期的amd64 CPU上, lahfsahf不可用。

而这基本上就是这一切!

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

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

这个问题更详细地介绍了被删除的指令,但是也有许多编码形式的含义被改变了。

例如,Jester在注释中给出了push eax在64位代码中无效的例子。 根据这个参考你可以看到,32位推送被标记为NE意思是不可编码的 。 在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的答案中找到,这是你应该阅读的。