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

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

问题描述

所有 x86 32 位汇编代码都是有效的 x86 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 根据 CS(代码段)寄存器中的段选择器执行 16 位或 32 位代码.启用分段,可以(并且通常)启用分页.通过远跳转到适当的段,程序可以在 16 位和 32 位代码之间切换.CPU 可以进入子模式虚拟 8086 模式,以在受保护模式的操作系统内部为各个进程模拟 实模式.
  • long 模式下, CPU 执行 64 位代码.分段主要是禁用的,分页是启用的.CPU 可以进入子模式兼容模式,在为长模式编写的操作系统中执行 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.每个寄存器都可以用作字节、字、双字或 qword 寄存器.REX 前缀系列(0x40 到 0x4f)对操作数是指旧寄存器还是新寄存器进行编码.另外还有 8 个 SSE/AVX 寄存器 xmm8、xmm9、...、xmm15 可用.
  • 您只能推送/弹出 64 位和 16 位数量(尽管您不应该这样做),不能推送/弹出 32 位数量.
  • 单字节 inc regdec reg 指令不可用,它们的指令空间已重新用于 REX 前缀.两字节的 inc r/mdec r/m 仍然可用,所以 inc regdec reg仍然可以编码.
  • 存在一种新的指令指针相对寻址模式,使用 32 位模式必须对 [disp32] 绝对地址进行编码的 2 种冗余方式中较短的一种.
  • 默认地址宽度为 64 位,可通过 0x67 前缀选择 32 位地址宽度.16 位寻址不可用.
  • 默认操作数宽度为 32 位.可以通过 0x66 前缀选择 16 位宽度,可以通过适当的 REX 前缀选择 64 位宽度,与您使用的寄存器无关.
  • 不能在需要的指令中使用 ahbhchdh一个 REX 前缀.REX 前缀使这些寄存器编号改为表示寄存器 sidispbp.
  • 写入 64 位寄存器的低 32 位会清除高 32 位,避免乱序执行的错误依赖.(写入 8 位或 16 位部分寄存器仍会与 64 位旧值合并.)
  • 由于分段是非功能性的,除了用于支持线程本地存储 (TLS).
  • 此外,许多专门处理分段的指令不可用.它们是:push/pop seg(除了push/pop fs/gs)、arplcall far(只有0xff编码有效)、lesldsjmp far(只有0xff编码有效)、
  • 处理十进制算术的指令不可用,它们是:daadasaaaaas, aam, aad,
  • 此外,以下指令不可用: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天全站免登陆