关于retrowin32的最常见问题 — 在“为什么要这样做?”之后- 是关于它实际上是如何工作的。这是一种现在对我来说显而易见的事情,但在我理解它之前这是一个很大的谜,所以在这里我希望以一种对你也很明显的方式来呈现它。
模拟 Windows API
首先,假设您在一台 x86 机器上运行 Windows 以外的操作系统,并且您想以某种方式运行 Windows 程序。 Wine(从首字母缩略词扩展来看,它不是模拟器)的主要观察结果是 Windows 可执行文件最终包含一堆 x86 指令,而您的 x86 已经能够直接执行它们。要执行 Windows .exe
,只需将其加载到内存中(这需要解压缩.exe
文件格式)并告诉处理器跳转到第一条指令。
唯一剩下的部分——一个巨大的部分——是这个 exe 如何与操作系统交互,例如打开文件或在屏幕上放置一些东西。这里的机制在操作系统之间有很大差异,但最终取决于内核的接口。在 Windows 的特定情况下,内核接口非常复杂(系统调用 ID 在 Windows 版本之间有所不同),并且稳定的 API 边界通常被理解为在 DLL 中,您可能会认出它们的名称,例如kernel32.dll
。 (这与 Linux 形成鲜明对比,众所周知,Linux 非常关心在内核边界拥有一个非常稳定的接口。)
其工作原理是.exe
文件格式可以声明“嘿,我需要调用kernel32.dll
的名为WriteFile()
的函数”,当加载.exe
时,操作系统会将适当的代码放在适当的位置,例如这个函数调用有效。在 Windows 上,kernel32 函数然后调用适当的内核接口。对于我们在非 Windows 操作系统上运行的目标,这很方便,因为我们需要做的就是提供我们自己的这些功能的实现,甚至无需考虑内核接口。
而这正是 Wine 所做的:它加载.exe
文件并提供所有 Windows DLL 的实现。它当然比实际情况要复杂得多,并且 Wine 见证了程序员几个世纪以来为提供 Windows 界面的所有角落和缝隙所做的努力,而这本身也见证了数十年的Hyrum 定律。
关于这个兔子洞能走多深的一个随机示例,请查看在 Wine 的系统调用调度程序中的 x86 程序集 blob 中找到的这个片段:
/* Legends of Runeterra hooks the first system call return instruction, and * depends on us returning to it. Adjust the return address accordingly. */ "subq $0xb,0x70(%rcx)\n\t"
Wine 的工作原理在 Wine 上有更深入的细节。上面有意省略了一些细节。
(顺便说一下,Wine 的一个简洁应用程序——与本文运行随机 exe 的目标完全无关——是如果你有 Windows 程序的源代码,你可以根据 Wine 的 Windows API 实现编译它并获得一个原生的可执行文件的另一边。)
模拟 x86
如果您使用的是 x86 硬件,以上内容都很好,但是如果您使用的是其他架构,比如这些基于 ARM 的新型 Mac,该怎么办?然后您必须模拟 x86 指令集,就像 Game Boy 模拟器可能模拟 Game Boy 的 CPU 一样。
这可不是小事!据报道,Apple 甚至为其 ARM 处理器添加了特殊的 x86 支持,以加快仿真速度。但是一旦您准备就绪,您就可以采用两种广泛的方法来处理其中的 Windows 部分。
一种是额外模拟 x86 机器上的所有硬件,例如 BIOS 和磁盘接口,这样您就可以将实际的 Windows 操作系统安装到您的模拟器中。这就是qemu采用的方法。在网络上, v86可以运行许多不同的操作系统,包括 Windows。
这种方法很棒,因为它运行的是 Windows 的真实副本,因此可以正确运行 Windows 程序。这种方法的主要缺点是它需要你安装一个真实的 Windows 副本,这也需要大量的磁盘空间和时间来启动 Windows,然后它才能执行任何操作。
第二种方法是只模拟 x86 指令集,并使用 Wine 如上所述作为大量 Windows API 的实现,支持更易于模拟的东西,例如 Linux 内核 API。在发布 retrowin32 之后,我了解了BoxedWine ,它可以在网络上执行此操作并且可以执行许多复杂的 Windows 程序。
retrowin32 的拍摄
我的 retrowin32 项目主要是探索我觉得有趣的东西。目前这意味着我有一个不太好的 x86 模拟器,一个不太好的 win32 实现,以及对相关任务的一些小探索。
总而言之,我认为如果您希望在 Web 上实际运行 Windows 程序,那么 BoxedWine 和 v86 可能会涵盖它。但是如果你对我的支线任务感到好奇,我打算写一篇关于 retrowin32 状态的后续文章。
原文: https://neugierig.org/software/blog/2023/01/emulating-win32.html