x86 32位汇编代码是有效的x86 64位汇编代码吗? [英] Is x86 32-bit assembly code valid x86 64-bit assembly code?

查看:190
本文介绍了x86 32位汇编代码是有效的x86 64位汇编代码吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is all x86 32-bit assembly code valid x86 64-bit assembly code?

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

I've wondered whether 32-bit assembly code is a subset of 64-bit assembly code, i.e., every 32-bit assembly code can be run in a 64-bit environment?

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

I guess the answer is yes, because 64-bit Windows is capable of executing 32-bit programs, but then I've seen that the 64-bit processor supports a 32-bit compatible mode?

如果不是,请提供一个无效的64位汇编代码的32位汇编代码示例,并说明64位处理器如何执行32位汇编代码.

If not, please provide a small example of 32-bit assembly code that isn't valid 64-bit assembly code and explain how the 64-bit processor executes the 32-bit assembly code.

推荐答案

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

A modern x86 CPU has three main operation modes (this description is simplified):

  • 实模式下, CPU在禁用分页和分段的情况下执行16位代码.代码中的内存地址是指物理地址,段寄存器的内容将被移位并添加到该地址中以形成有效地址.
  • 保护模式中,CPU执行16位或32位代码,具体取决于CS(代码段)寄存器中的段选择器.启用分段后,可以(通常)启用分页.程序可以通过跳到适当的段来在16位和32位代码之间切换. CPU可以进入子模式虚拟8086模式,以从保护模式操作系统内部为各个进程模拟实模式.
  • long模式下, CPU执行64位代码.大多数情况下,分段是禁用的,分页是启用的. CPU可以进入子模式兼容模式以从为 long模式编写的操作系统中执行16位和32位保护模式代码. 兼容模式是通过跳到设置了适当位的CS选择器输入的. 虚拟8086模式不可用.
  • In real mode, the CPU executes 16 bit code with paging and segmentation disabled. Memory addresses in your code refer to phyiscal addresses, the content of segment registers is shifted and added to the address to form an effective address.
  • In protected mode, the CPU executes 16 bit or 32 bit code depending on the segment selector in the CS (code segment) register. Segmentation is enabled, paging can (and usually is) enabled. Programs can switch between 16 bit and 32 bit code by far jumping to an appropriate segment. The CPU can enter the submode virtual 8086 mode to emulate real mode for individual processes from inside a protected mode operating system.
  • In long mode, the CPU executes 64 bit code. Segmentation is mostly disabled, paging is enabled. The CPU can enter the sub-mode compatibility mode to execute 16 bit and 32 bit protected mode code from within an operating system written for long mode. Compatibility mode is entered by far-jumping to a CS selector with the appropriate bits set. Virtual 8086 mode is unavailable.

维基百科的 x86-64操作模式(包括旧版)和实模式,以及长模式的所有3个子模式.在主流的x86-64操作系统下,启动后,CPU内核将始终处于长模式,并根据32位或64位用户空间在不同的子模式之间进行切换. (不计算系统管理模式中断...)

Wikipedia has a nice table of x86-64 operating modes including legacy and real modes, and all 3 sub-modes of long mode. Under a mainstream x86-64 OS, after booting the CPU cores will always all be in long mode, switching between different sub-modes depending on 32 or 64-bit user-space. (Not counting System Management Mode interrupts...)

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

Now what is the difference between 16 bit, 32 bit, and 64 bit mode?

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

16-bit and 32-bit mode are basically the same thing except for the following differences:

  • 在16位模式下,默认地址和操作数宽度为16位.您可以分别使用0x67和0x66前缀将这些指令更改为32位.在32位模式下,情况恰恰相反.
  • 在16位模式下,指令指针被截断为16位,跳转到高于65536的地址会导致奇怪的结果.
  • VEX/EVEX编码的指令(包括AVX,AVX2,BMI,BMI2和AVX512指令集的指令)不会在实数或虚拟8086模式下解码(尽管它们在16位保护模式下可用).
  • 16位模式的寻址模式比32位模式的寻址模式少,但是如果需要的话,可以根据每条指令改写为32位寻址模式.

现在,64位模式有些不同.大多数指令的行为就像在32位模式下一样,但有以下区别:

Now, 64 bit mode is a somewhat different. Most instructions behave just like in 32 bit mode with the following differences:

  • 还有八个名为r8,r9,...,r15的附加寄存器.每个寄存器都可以用作字节,字,dword或qword寄存器. REX前缀家族(0x40至0x4f)对操作数是引用旧寄存器还是引用新寄存器进行编码.还提供了八个额外的SSE/AVX寄存器xmm8,xmm9,...,xmm15.
  • 您只能推送/弹出64位和16位的数量(尽管您不应该这样做),不能推送/弹出32位的数量.
  • 单字节inc regdec reg指令不可用,它们的指令空间已重新用于REX前缀.两字节的inc r/mdec r/m仍然可用,因此inc regdec reg仍然可以编码.
  • 存在一种新的指令指针相对寻址模式,使用32位模式必须对[disp32]绝对地址进行编码的两种冗余方式中的较短者.
  • 默认地址宽度为64位,可以通过0x67前缀选择32位地址宽度. 16位寻址不可用.
  • 默认操作数宽度为32位.可以通过0x66前缀选择16位的宽度,可以通过适当的REX前缀选择64位的宽度,而与所使用的寄存器无关.
  • 在需要REX前缀的指令中不能使用ahbhchdh. REX前缀使这些寄存器号表示的是寄存器sidispbp的低8位.
  • 写入64位寄存器的低32位将清除高32位,从而避免错误的exec依存关系. (写入8或16位部分寄存器仍会与64位旧值合并.)
  • 由于分段是不起作用的,因此分段覆盖是没有意义的无操作,除了fsgs覆盖(0x64、0x65)(用于支持线程本地存储(TLS))之外.
  • 同样,许多专门用于细分的指令也不可用.它们是:push/pop seg(push/pop fs/gs除外),arplcall far(仅0xff编码有效),lesldsjmp far(仅0xff编码有效), 无法使用用于处理十进制算术的
  • 指令,它们是:daadasaaaaasaamaad
  • 此外,以下指令不可用:bound(很少使用),pusha/popa(对于其他寄存器不可用),salc(未公开),
  • 0x80的0x82指令别名无效.
  • 在早期的amd64 CPU上,lahfsahf不可用.
  • There are eight additional registers named r8, r9, ..., r15. Each register can be used as a byte, word, dword, or qword register. The family of REX prefixes (0x40 to 0x4f) encode whether an operand refers to an old or new register. Eight additional SSE/AVX registers xmm8, xmm9, ..., xmm15 are also available.
  • you can only push/pop 64 bit and 16 bit quantities (though you shouldn't do the latter), 32 bit quantities cannot be pushed/popped.
  • The single-byte inc reg and dec reg instructions are unavailable, their instruction space has been repurposed for the REX prefixes. Two-byte inc r/m and dec r/m is still available, so inc reg and dec reg can still be encoded.
  • A new instruction-pointer relative addressing mode exists, using the shorter of the 2 redundant ways 32-bit mode had to encode a [disp32] absolute address.
  • The default address width is 64 bit, a 32 bit address width can be selected through the 0x67 prefix. 16 bit addressing is unavailable.
  • The default operand width is 32 bit. A width of 16 bit can be selected through the 0x66 prefix, a 64 bit width can be selected through an appropriate REX prefix independently of which registers you use.
  • It is not possible to use ah, bh, ch, and dh in an instruction that requires a REX prefix. A REX prefix causes those register numbers to mean instead the low 8 bits of registers si, di, sp, and bp.
  • writing to the low 32 bits of a 64 bit register clears the upper 32 bit, avoiding false dependencies for out-of-order exec. (Writing 8 or 16-bit partial registers still merges with the 64-bit old value.)
  • as segmentation is nonfunctional, segment overrides are meaningless no-ops except for the fs and gs overrides (0x64, 0x65) which serve to support thread-local storage (TLS).
  • also, many instructions that specifically deal with segmentation are unavailable. These are: push/pop seg (except push/pop fs/gs), arpl, call far (only the 0xff encoding is valid), les, lds, jmp far (only the 0xff encoding is valid),
  • instructions that deal with decimal arithmetic are unavailable, these are: daa, das, aaa, aas, aam, aad,
  • additionally, the following instructions are unavailable: bound (rarely used), pusha/popa (not useful with the additional registers), salc (undocumented),
  • the 0x82 instruction alias for 0x80 is invalid.
  • on early amd64 CPUs, lahf and sahf are unavailable.

基本上就是全部!

这篇关于x86 32位汇编代码是有效的x86 64位汇编代码吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆