为啥英特尔微处理器的 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
的情况是mov
有REX
前缀。
来自:http://www.felixcloutier.com/x86/MOV.html
***在 64 位模式下,如果使用 REX 前缀,则 r/m8 无法编码以访问以下字节寄存器:
AH
、BH
、CH
、DH
。
在这种情况下,高字节寄存器(AH
、BH
、CH
和 DH
)被重新定义为
DIL
、SIL
、BPL
和 SPL
。但这仅在存在 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?的主要内容,如果未能解决你的问题,请参考以下文章