3

我了解今天使用最新编译器(GCC、Intel CC、VC 等)编译的所有 x86 (i386) 二进制文件都将在 Intel 386 机器上运行(允许外部依赖,如 OS 函数等),这解释了为什么有YouTube 上关于人们让 Windows 7 在 20 年前的计算机上安装和运行的视频。

但我不明白 ISA 扩展是如何工作的,例如 MMX 和 SSE。如果程序的代码有扩展指令,但处理器不支持该指令,那么程序肯定会崩溃(可能是处理器中断进入操作系统)。我能想到的唯一解决方案是程序的二进制文件检查是否支持指令,如果不支持,则执行保证每个平台都支持的最低公分母代码,但这肯定会使二进制文件非常大,那么那些是扩展但现在实际上是标准的指令呢,比如浮点运算?这是否意味着执行 FP 操作的每个 i386 二进制文件还包括软件 FP 仿真?

如果一个程序进行指令支持的检查,那么它在哪里进行呢?如果您有一个紧密的循环,那么您不希望它在循环内执行检查。我不相信编译器足够聪明,还不知道如何在每种情况下进行优化,因此缺乏可见的编译器选项很奇怪。

我在我的 VC 项目设置中找不到用于控制指令发射的编译器或链接器的任何设置或选项。有一些关于优化的内容,但没有任何东西可以提供我期望的控制。

那么 AMD 的“3DNow!”呢?扩大?3DNow 旨在成为 MMX 之上的扩展,因此它有一些独特的指令和自身的方面,但我在我的 VC 编译器或链接器设置中找不到对它的任何引用,所以如果我正在编写代码如何我可以让我的编译器使用 3DNow!指令(而不是 MMX)?

此外,关于 3DNow 的 Wikipedia 文章指出,AMD 从其处理器中删除了一些 3DNow 指令 - 如果存在假设这些指令存在的代码,它将不再起作用吗?

4

2 回答 2

3

I understand that all x86 (i386) binaries compiled today, with the latest compilers (GCC, Intel CC, VC, etc) will run on an Intel 386 machine (allowing for external dependencies, like OS functions, etc) which explains why there are videos on YouTube of people getting Windows 7 to install and run on a 20 year-old computer.

Not really. Intel 386 did not have cmpxchg8b that is required for Windows Vista or Windows 7. After a certain update, Windows 7 requires SSE2.

But I don't understand how ISA extensions work, such as MMX and SSE. If a program's code has an extension instruction but the instruction is not supported by the processor then surely the program must crash (presumably a processor interrupt into the OS). The only solution I can think of is that the program's binary checks to see if an instruction is supported, and if not then it executes lowest-common-denominator code that is guaranteed to be supported by every platform, but surely that can make binaries very large, and what about instructions that were extensions but are now practically standard, like floating-point operations?

Runtime feature dispatch is a thing, and it is used in some programs and libraries, but often the code is compiled to require certain instructions.

Even if there is runtime feature dispatch, it is often used to detect relatively new extensions, while old extensions are mandatory.

/arch:SSE2 is default in Visual Studio 2012 and later, so normally programs will not use legacy floating point operations.

An example of runtime dispatch is vector_algorithms.cpp from MSVC STL where AVX2 and SSE2 are checked for availability at runtime. In x86 mode they fall back to plain C++ code which is complied not to emit vectored instructions, in x64 mode the use of SSE2 is unconditional, as SSE2 is the baseline for x64.

I can't find any settings or options in my VC project settings for the compiler or linker for controlling instruction emission. There are a few about optimization but nothing that gives the control I expect.

/arch switch. From IDE, "Enable Enhanced Instruction Set" in C/C++ compiler options.

And what about AMD's "3DNow!" extension? 3DNow is meant to be an extension on top of MMX, so it has some unique instructions and aspects of its own, but I can't find any references to it in my VC compiler or linker settings, so if I'm writing code how can I get my compiler to use the 3DNow! instructions (rather than MMX)?

Visual Studio is not able to use them during auto-vectorizing (never auto-vectorized using them). As for intrinsic form, surprisingly you can still use them in x86 mode (but not x64 mode).

Also, the Wikipedia article on 3DNow states that AMD removed a few 3DNow instructions from their processors - if there exists code that assumes these instructions are present will it no-longer work?

To clarify, instructions are removed in a sense that new processors don't have them. They are not removed by a microcode update from old processor.

Instructions removed to complete non-existence, attempts to use them may raise #UD exceptions, or their encoding may be re-purposed for other instructions.

于 2021-10-13T10:21:45.147 回答
1

据我了解,这些扩展在新的时候并不经常使用。如今,这些扩展是给定的(使用 AMD64 时)或假定的(使用 IA-32 时)。过去,只有在真正需要这些扩展时,例如在开发数学库时,您才会真正受益于这些功能。在这种情况下,您正在做非常具体的工作,可能会花时间决定如何处理向后兼容性。您基本上有两个选择,或者您通过软件实现提供向后兼容性,或者您不支持旧平台或不支持这些平台上的特定功能。根据维基百科,有第三种选择:

在其他情况下,操作系统可能会模仿旧处理器的新功能,但通常会降低性能。

这似乎意味着操作系统将以某种方式捕获不受支持的指令并用软件实现替换它们。来自维基百科的参考链接也已失效且未存档,但我发现了另一条线索

IA-32 CPU 在运行二进制程序时遇到未知指令会产生异常,即#UD(未定义)异常。此异常归结为类 UNIX 操作系统中的 SIGILL 信号。 模拟指令的想法是,钩住这个异常,在异常处理程序中做正确的事情,然后返回主程序。因此,CPU 必须在我们要模拟的每条指令上生成异常。

但是,相信对此答案的评论,这些操作系统实现不再是一回事了。

于 2021-10-13T09:19:06.393 回答