x86 已经发生了多次显着的发展,但需要硬件来保持与旧二进制文件的向后兼容性。例如,现代 x86 硬件仍然包含对本地运行 16 位代码的支持。此外,还存在多种内存寻址模型,允许旧代码在同一处理器上互操作,例如实模式、保护模式、虚拟 8086 模式和 (amd64) 长模式。这可能会让一些人感到困惑。
x86 是 CISC 机器。长期以来,这意味着它比 MIPS 或 ARM 等 RISC 机器慢,因为指令具有数据相互依赖性和标志 https://stackoverflow.com/a/2680041/82320使得大多数形式的指令级并行性难以实现。现代实现将 x86 指令转换为类似于 RISC 的指令,称为“微操作 https://en.wikipedia.org/wiki/Micro-operation“在幕后使这些优化能够在硬件中实现。
在某些方面,x86 并不逊色,只是有所不同。例如,输入/输出在绝大多数体系结构上被处理为内存映射,但在 x86 上则不然。 (注意:现代 x86 机器通常具有某种形式的DMA https://en.wikipedia.org/wiki/Direct_memory_access通过内存映射支持并与其他硬件进行通信;但是ISA https://en.wikipedia.org/wiki/Instruction_set仍然有 I/O 指令,例如IN and OUT)
The x86 ISA https://en.wikipedia.org/wiki/Instruction_set具有很少的体系结构寄存器,这可能会迫使程序比其他必要的情况更频繁地往返内存。执行此操作所需的额外指令会占用本可以用于有用工作的执行资源,尽管高效的存储转发 https://en.wikipedia.org/wiki/Memory_disambiguation#Store_to_load_forwarding保持低延迟。将寄存器重命名到大型物理寄存器文件的现代实现可以使许多指令保持运行,但缺乏架构寄存器仍然是 32 位 x86 的一个重大弱点。 x86-64 从 8 个整数和向量寄存器增加到 16 个,是 64 位代码比 32 位代码更快的最大因素之一(以及更高效的寄存器调用 ABI),而不是每个寄存器宽度的增加。将整数寄存器从 16 个进一步增加到 32 个会有所帮助,但效果不大。 (不过,AVX512 确实增加到了 32 个向量寄存器,因为浮点代码具有更高的延迟,并且通常需要更多常量。)(看评论 https://stackoverflow.com/questions/2679882/why-is-x86-ugly-aka-why-is-x86-considered-inferior-when-compared-to-others/2679922?noredirect=1#comment56088321_2679922)
x86 汇编代码很复杂,因为 x86 是一个具有许多功能的复杂架构。典型 MIPS 机器的指令列表适合一张信纸大小的纸。 x86 的等效列表占据了好几页,并且说明的作用更多,因此您通常需要比列表所能提供的更详细的解释来说明它们的功能。例如,MOVSB操作说明 https://en.wikipedia.org/wiki/X86_instruction_listings#Original_8086.2F8088_instructions需要一段相对较大的 C 代码块来描述它的作用:
if (DF==0)
*(byte*)DI++ = *(byte*)SI++;
else
*(byte*)DI-- = *(byte*)SI--;
虽然 MIPS(和类似的体系结构)的简单性并不一定使它们优越,但对于汇编程序类的介绍来说,从更简单的开始是有意义的ISA https://en.wikipedia.org/wiki/Instruction_set。一些汇编课程教授 x86 的一个超简化子集,称为y86 https://esolangs.org/wiki/Y86,它被简化到对实际使用没有用处(例如没有移位指令),或者有些只教授基本的 x86 指令。
x86 使用可变长度操作码,这增加了指令解析的硬件复杂性。在现代,随着 CPU 越来越受到内存带宽的限制(而不是原始计算的限制),这一成本变得微乎其微,但许多“抨击 x86”的文章和态度都来自这一成本相对要大得多的时代。 2016 年更新:Anandtech 发布了关于 x64 和 AArch64 下操作码大小的讨论 http://www.anandtech.com/show/9766/the-apple-ipad-pro-review/3.