为啥英特尔微处理器的 64 位模式不支持 MOV AH,1?

Posted

技术标签:

【中文标题】为啥英特尔微处理器的 64 位模式不支持 MOV AH,1?【英文标题】:Why MOV AH,1 is not supported in 64 bit mode of intel microprocessor?为什么英特尔微处理器的 64 位模式不支持 MOV AH,1? 【发布时间】:2017-07-13 14:32:39 【问题描述】:

在 Barry B. Brey 的《THE INTEL MICROPROCESSORS》一书中,写到

MOV AH, 1

在 64 位模式下不允许,但在 32 位或 16 位模式下允许。如果MOV AL, 1可以在64位模式下允许,MOV AH, 1有什么问题?

【问题讨论】:

那本书是错的。 "the book of Barry B. Brey" ← 指书的方式真奇怪。那本书没有你可以给我们的书名吗? @CodyGray 已编辑 【参考方案1】:

mov ah,1 没有问题。它在 X64 模式下运行良好。

它的操作码是b4 01

唯一不允许mov ah 的情况是movREX 前缀。

来自:http://www.felixcloutier.com/x86/MOV.html

***在 64 位模式下,如果使用 REX 前缀,则 r/m8 无法编码以访问以下字节寄存器:AHBHCHDH

在这种情况下,高字节寄存器(AHBHCHDH)被重新定义为 DILSILBPLSPL。但这仅在存在 REX 前缀的情况下。

带有 REX 前缀的指令是:

anything with the R8..R15 regs and parts thereof
anything that accesses the new 8 bit regs: DIL, SIL, BPL, SPL
anything that accesses 64 bit registers.

【讨论】:

所以我不能使用像 MOV AH、R10B 这样的指令,但是我可以在 64 位模式下使用像 MOV AH、BL 和 MOV AL、R10B 这样的指令。我说的对吗? 没错,@lab11。唯一不能使用 AH、BH、CH 或 DH 的情况是当您使用 DIL、SIL、BPL、SPL、R8B、R9B、R10B、R11B、R12B、R13B、R14B 或 R15B 作为另一个操作数时,因为所有这些需要一个 REX 前缀。就试一试吧;如果有问题,你的汇编程序会告诉你! @CodyGray:一个更重要的障碍是像movzx r10d, ah 这样的东西是不可编码的。甚至movsx rdi, ah。此外,mov [r10], ah 不可编码,因为这需要基址寄存器的 REX 前缀。在 x86-64 中,AH 的主要用途是在将 RAX 分割成字节时节省移位。 (或者在没有部分注册停顿的 CPU 上,将字节合并为更宽的整数)。您通常不需要仅仅因为寄存器压力而将 AL 和 AH 用作单独的字节寄存器。【参考方案2】:

还请注意,根据英特尔优化手册,不鼓励某些处理器使用 8 位寄存器,而其他处理器则不建议使用。目前,它只是不鼓励 Knights Landing,但将来 8 位和 16 位指令工作速度较慢的处理器列表可能会增加。英特尔在手册中写道:

在 Knights Landing 微架构中的硬件中未对 8 位或 16 位寄存器进行操作的指令进行优化。一般来说,在 32 位或 64 位通用寄存器上使用整数指令比 8 位或 16 位寄存器更快。

虽然 Knights Landing 不是通用 CPU,但我预计在所有未来处理器上,可能会在下一个主要微架构更改中,即 Icelake 微架构,这是基于英特尔 CPU 微架构的预计在 2019 年取代 Cannonlake 的 10nm 节点 - 8 位和 16 位寄存器操作会很慢,不仅写入,读取也会(免责声明:我的这种预期纯属猜测)。

所以,回到 ah 寄存器 - 例如,您无法在 64 位模式下编码 movzx r8, ah,但您可以使用 ah 寄存器本身对任何内容进行编码,例如mov ah, 1 - 因为 AMD 设计了 ​​64 位模式,使旧指令的编码方式与旧 32 位模式相同。

【讨论】:

王者登陆不是通用CPU。它用于科学计算目的。 如果你的预测成真,对于SETcc 指令来说将是非常个坏消息,它仍然需要 8位寄存器操作数.由于需要前缀,16 位寄存器操作已经有点慢,但是 8 位并没有真正慢。事实上,由于最大限度地减少了部分寄存器停顿的影响,它现在比多年来更快。当他们说“未在硬件上进行优化”时,我不知道英特尔是什么意思。我有点怀疑你的预测会成真。出于多种原因,KNL 是一种非常不寻常的微架构,我怀疑它是否会成为主流。 loop 从来没有特别有用,因为它完全等同于dec cx+jnz Label。它从未真正受到编译器的欢迎,英特尔不再试图让它变得更快。它也是 x86 的 CISC 遗产的一部分,在 x86 内部转换为 RISC 后,它不再快速。我认为 8 位和 16 位指令根本无法与之相比。另外,就像我说的,有一些需要 8 位寄存器操作数的 important 指令,比如SETcc,只是没有很好的替代品。如果 KNL 已经介绍了SETcc r32,那就太棒了! @CodyGray:Skylake 的 AH 已经很慢,但 AL 仍然很快。 (movzx edx, ah:2c 延迟。movzx edx, al:0c 延迟,已消除。movzx eax, al:1c 延迟,由于相同的寄存器而未消除)。如果英特尔制造 AL​​/R8B/等,我会感到惊讶。 Cannonlake 的速度很慢,因为许多真正的编译器生成的代码使用低字节寄存器。这是可能的,尤其是。如果他们提前开始编译器更改。或者,也许他们只会把我们搞砸,使大量现有代码次优,直到人们使用全新的编译器版本重新编译。 @CodyGray 和 Maxim:我的猜测是英特尔手册中的这一段是对 Silvermont/KNL 不会单独重命名部分寄存器这一事实的过度简化,因此 mov al, 1 有一个错误依赖于 EAX 的旧值,即使您从未真正阅读过 EAX。此外,引用的文本出现在 KNL 章节的“标志用法”部分。 (有趣的事实:KNL 在dec / jnz 上有标志合并档位,所以请改用sub reg,1。我想我最好去更新我的避免-inc-is-only-for-P4 答案!)

以上是关于为啥英特尔微处理器的 64 位模式不支持 MOV AH,1?的主要内容,如果未能解决你的问题,请参考以下文章

英特尔RFLAGS和POPFQ PUSHFQ?

为啥 .NET 不支持 32 位的 SSE(而 ryujit 64 位可以)而 Mono 支持 32 位和 64 位?

为啥Adobe Flash Player不支持64位浏览器

第十一课 实模式到保护模式 中

X86-64 汇编学习1

X86-64 汇编学习1