【问题标题】:Assembly: why some x86 opcodes are invalid in x64?汇编:为什么某些 x86 操作码在 x64 中无效?
【发布时间】:2015-09-05 10:43:50
【问题描述】:

为什么在 x64 中某些操作码无效(例如0607),而在 x86 中用于相当基本的指令(0607pushpop) ?我认为那些最简单的指令在这两种架构中都能很好地发挥作用。

为什么他们在 x64 中禁用了一些简单的指令?为什么他们不工作? 为什么他们禁用了一些操作码,在操作码列表中创建了漏洞,而他们可以将它们分配给 x64 版本的指令?

参考:

http://ref.x86asm.net/coder32.html

http://ref.x86asm.net/coder64.html

【问题讨论】:

标签: assembly x86 x86-64 cpu-architecture opcode


【解决方案1】:

32 位模式下的0607 操作码是指令PUSH ESPOP ES。在 64 位模式下,段寄存器 CS、DS、ES 和 SS 不再用于确定内存地址:处理器假定基地址为 0,并且没有大小限制。由于现在应用程序(除了操作系统本身)通常没有理由访问这些寄存器,因此删除了用于更改和访问它们的 push/pop 操作码,只留下了 mov 到/来自 Sreg(总共只有 2 个操作码; 寄存器编号进入 ModRM 字节而不是 1 字节操作码的一部分)。这对于几乎不需要的东西来说已经足够了。

FS 和 GS 段寄存器在 64 位模式下仍然可以设置基地址,因此与它们相关的 push 和 pop 操作码没有被删除。 (这些 2 字节的 0F xx 操作码是在 386 中添加的,与用于 8086 段寄存器的旧的 1 字节操作码相比,它们在操作码空间中的价值较低)。

段寄存器的推送/弹出或mov 不是操作系统通常设置 FS 或 GS​​ 段基数的方式:这需要 GDT 或 LDT 条目,并且只能在低 32 位内设置基数。 64 位操作系统将使用相关的 MSR 直接读取和写入基址,而不是架构寄存器。 (现代 32 位操作系统也这样做,除非在不支持分段基础 MSR 的旧硬件上运行。)

【讨论】:

  • CS其实还在用。
  • @harold 没错,它仍然是用来设置代码段的属性(例如启用64位模式),但不再用于确定内存地址。
  • @interjay:我做了一些重要的修改;您的回答似乎暗示推送/弹出是访问这些注册表的唯一方法,更不用说mov。还暗示 FS 或 GS​​ 基数是通过pop 设置的,而不是wrmsr。即使仍然可以使用 seg reg,操作系统可能仍会使用平面内存模型,因此删除这些 reg 的 push/pop 并只留下 mov 仍然是一个明智的设计。
【解决方案2】:

对于所有 CPU,都有类似于“操作码空间”的东西。例如,如果 CPU 使用 8 位操作码,那么将有一个最大值。它可能有 256 条指令。操作码越大,您可以拥有的操作码就越多,但越难快速获取和解码。

80x86 是一种比较古老的架构。它从一个适度的操作码空间开始,主要由 1 字节和 2 字节的操作码组成。每次 CPU 制造商添加新功能时,都会从操作码空间中获取更多操作码。他们用完了操作码。他们很快就跑出去了。

为了解决这个问题,他们开始做一些事情,比如添加转义码和前缀来人为地扩展操作码空间。例如,对于最近的 AVX 指令,您正在查看 VEX 前缀,后跟旧的/回收的转义码(例如 0xF0),后跟旧的/回收的地址/操作数大小前缀(例如 0x66),然后是另外 4 个字节.不好看。

同时,还有现在很少使用的旧指令(AAD、AAM 等)和具有多个/冗余操作码 (INC/DEC) 的指令正在消耗宝贵的“1 字节”操作码。由于向后兼容性,这些不能/不能完全删除。

但是;在设计 64 位时,根本没有任何 64 位代码可以兼容——向后兼容并不重要。被“不是很重要”的指令消耗的 1 字节操作码可以被回收;使这些指令在 64 位代码中无效(但释放了一些有价值的 1 字节操作码)。

这些 1 字节操作码中的大多数(如果我没记错的话,整个 1 字节 INC/DEC 组)立即被回收用于支持 64 位操作数所需的 REX 前缀。有些不是,而是“对未来的扩展免费”(限制是扩展只能在 64 位代码中工作,因为这些指令在 16 位和 32 位代码中仍然有效)。

【讨论】:

  • 对于 AMD64 模式,可能已经删除了其他指令。他们甚至可以完全重新设计二进制编码。我认为 进行许多更改的原因是相同的芯片可以解码 32 位和 64 位模式,而没有太多取决于 CPU 处于何种模式的条件逻辑。
  • @PeterCordes:是的。请注意,在引入 64 位 80x86 时,英特尔试图将所有需要 64 位的人推向替代方案(安腾);如果安腾成功了,AMD 就死定了(安腾没有交叉许可协议)。通过使 64 位与现有的 32 位基本相同,他们减少了发布 CPU 所需的时间以及其他人(编译器、操作系统)支持它所需的时间;并防止了“为时已晚”的灾难。这在当时是正确的决定(但来自 64 位 ARM 的日益激烈的竞争使其“从长远来看是不幸的”)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 2022-11-24
  • 2012-08-02
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
相关资源
最近更新 更多