1

我最近对了解低级计算很感兴趣。我了解当今广泛使用的计算机遵循 x86/x86-64 架构。

据我了解,架构,更具体地说,指令集架构 (ISA) 是程序员能够向 CPU 发出的指令集。

第一个问题,ISA 是在不断发展还是保持不变?

我认为它在不断发展(意味着新指令不断被添加/以前的指令被修改?)但是旧处理器如何能够执行用新指令编写的代码?(它不知道新指令,但应该能够执行代码,因为它具有 x86 架构)。编译器处理这个东西还是处理器?基本上,相同的指令集合如何能够在所有新旧处理器上运行?

最后,除了程序员不关心的微架构(如果我错了,请纠正我),程序员在处理新处理器时会看到哪些变化?由于微架构的变化,旧的指令可能会因为高效的执行而运行得很快。但是引入的新指令是否允许以前无法完成的事情?或者以前可以用一堆指令完成什么,但由于硬件的变化,现在可以用一个指令完成?新的寄存器?还要别的吗?

它是否做了类似的事情 - 如果处理器支持这个新的强大指令以更快地执行,那么使用新指令,否则回退到较慢的旧指令。如果是,谁执行这个 if - else 子句?编译器?如果没有,那会发生什么?

4

1 回答 1

9

与大多数 ISA 一样,x86 也在不断发展。

一些 ISA 通过重新定义现有的操作码(例如 MIPS64r6 这样做)来破坏向后兼容,但这种情况很少见。例如 MIPS32r6 / MIPS64r6 就是一个例子:https ://en.wikipedia.org/wiki/MIPS_architecture#MIPS32/MIPS64_Release_6重新定义了几种编码,以及删除了一些指令。

x86从未破坏向后兼容:Ryzen 或 Skylake-X 仍然可以启动和运行在 8086 上工作的机器代码。这就是 x86 CPU 的一部分含义:另请参阅x86 的开始:英特尔 8080 与英特尔 8086?. (我们只是在谈论机器代码,但如果您以传统 BIOS 模式而不是 UEFI 启动 PC,那么即使是 I/O 设备也会被模拟,因此像早期 DOS 这样的非常早期的 8086 PC 操作系统实际上可能会在本地运行。)

英特尔计划从其芯片组中删除一些传统的 IBM-PC 硬件仿真支持,如 PIC、PIT、A20 门。并且放弃对传统 BIOS 启动 (CSM) 的支持,只支持 UEFI,但 CPU 本身仍将支持切换回实模式。

英特尔和 AMD 将这一点发挥到了极致,以至于当前 CPU 上的 16 位和 32 位模式仍然支持像 SALC(类似但没有更新 FLAGS)这样的未记录的 8086 指令sbb al,al这会占用宝贵的操作码编码空间,这些空间可用于较短的编码新的指令。

但是使用新 insn 的 SW 仅适用于新 HW。新软件将在当前和未来的硬件上运行,而旧硬件则可以选择与之兼容。(例如,在 32 位代码中,您可能会避免使用cmovPentium Pro 的新指令或其他指令,因此您的代码可以在 P5 (i586) Pentium / PMMX 上运行。)

x86-64 设置了一个新基线,其中包括 SSE2 和 PPro 指令,如cmov. 幸运的是,64 位代码不必担心与没有这些东西的旧 CPU 兼容,x86-64 需要它们。

包含 AVX2、FMA 和 BMI2(例如 Haswell)的新基线会非常好。如果您的编译器可以在整个代码中的任何地方使用 BMI1/BMI2 来实现更有效的变量计数移位指令等,而不仅仅是像 SIMD 指令那样的几个热循环,那么 BMI1/BMI2 尤其有用。但英特尔仍在销售不带 BMI2 的新 CPU(例如 Pentium/Celeron 版本的 Skylake/Coffee Lake。)

如果没有,那会发生什么?

CPU 不支持的指令通常会出现#UD(UnDefined)错误。在类 Unix 操作系统上,您的进程将收到 SIGILL(非法指令信号。

(有趣的事实:原始 8086 没有 #UD 异常;每个字节序列都被解码为某种东西。)

制作一个能够利用新指令但不会在旧 CPU 上触发非法指令错误的二进制文件的唯一方法是执行运行时 CPU 检测和动态调度。一些编译器可以为您做到这一点。

新指令的编码可能(在旧 CPU 上)看起来像是不同指令的冗余前缀。例如lzcnt,在不支持它的 CPU 上将解码为rep bsr,它运行为bsr. 并给出不同的结果lzcnt

(英特尔的文档明确指出,未来的 CPU 不能保证像当前 CPU 那样解码带有无意义前缀的指令。这为他们留下了以这种方式进行 ISA 扩展的空间。)

有时,对旧 CPU 上无意义的 REP 前缀的静默忽略对 ISA 扩展很有用。例如pauserep nop。它在旧 CPU 上无害地解码非常有用,允许将其放置在自旋循环中而无需检查。类似地,硬件锁省略(事务性内存)解码为仍然可以在旧 CPU 上运行的代码,实际上是在执行原子操作而不是开始事务。


另见:停止指令集战争,由 Agner Fog 撰写。英特尔通过不发布即将推出的 ISA 扩展的详细信息来搞砸 AMD 的一些历史,因此 AMD 最终开发了自己的不兼容的产品,并花费了更多年时间来为自己的 CPU 添加对新扩展的支持。(例如,SSSE3 在 Bulldozer 之前的 AMD CPU 上不可用,这意味着即使是需要新计算机的游戏也不能将其作为基准多年,而 Phenom-II CPU 仍然存在。)


但是引入的新指令是否允许以前无法完成的事情?

8086 是图灵完备的(有限内存除外),因此“无法完成”的最重要形式是寻址更多内存:386 中的 32 位地址,x86 中的 64 位地址(错误 48 虚拟/52 物理)- 64. 但是这些都是通过引入全新的模式来实现的。他们还引入的新指令是另一回事。

但是,如果您的意思是“无法有效完成

是的,SIMD 是最重要的例子之一。MMX,然后是 SSE/SSE2,然后是 SSE4.x。然后 AVX 是两倍宽的向量。并行处理 16 或 32 字节数据的整个向量可以极大地加速strlenmemcmp与一次一个字节的循环相比。对于很多数组的东西也很有帮助。

AVX2 基于面具的最有效打包方式是什么?是新指令集启用的新技巧的一个有趣示例。例如,AVX512 内置了这个操作,而 AVX2 + BMI2 允许使用pdep/的技巧,pext这是以前不可能的。

SSSE3pshufb是第一个可变控制 shuffle 指令,从查找表中加载 shuffle-control 可以实现以前无法有效实现的事情。例如从字符串获取 IPv4 地址的最快方法

如何使用 SIMD 实现 atoi?还展示了您可以使用 x86 的pmaddubsw/pmaddwd整数乘法 + 水平加法指令执行的一些漂亮操作,以乘以小数位值。


在 8086 之后添加的新指令的早期历史很好地记录在NASM 手册附录的错误修复分支中。本附录的当前版本删除了每条指令的文本描述,以便为 SIMD 指令腾出空间。(有很多。)

A.5.118 IMUL: Signed Integer Multiply
IMUL r/m8                     ; F6 /5                [8086]
IMUL r/m16                    ; o16 F7 /5            [8086]
IMUL r/m32                    ; o32 F7 /5            [386]

IMUL reg16,r/m16              ; o16 0F AF /r         [386]
IMUL reg32,r/m32              ; o32 0F AF /r         [386]

IMUL reg16,imm8               ; o16 6B /r ib         [186]
IMUL reg16,imm16              ; o16 69 /r iw         [186]
IMUL reg32,imm8               ; o32 6B /r ib         [386]
IMUL reg32,imm32              ; o32 69 /r id         [386]

IMUL reg16,r/m16,imm8         ; o16 6B /r ib         [186]
IMUL reg16,r/m16,imm16        ; o16 69 /r iw         [186]
IMUL reg32,r/m32,imm8         ; o32 6B /r ib         [386]
IMUL reg32,r/m32,imm32        ; o32 69 /r id         [386]

当然,任何 reg32 指令都需要 386 来进行 32 位扩展,但请注意 imul-immediate 在 186 ( imul cx, [bx], 123) 中是新的,而 2 操作数 imul 在 386 ( imul cx, [bx])中是新的,允许在不破坏 DX:AX 的情况下进行乘法运算,从而使 AX 不那么“特殊” ”。

其他 386 条指令在使寄存器更加正交方面也大有帮助,让您可以有效地对任何寄存器进行符号扩展movsxmovzx在此之前,您必须将数据输入 AL 并使用cbw,或输入 AXcwd以签名扩展为 DX:AX。

于 2018-12-19T15:28:04.820 回答