为什么 64 位程序无法在 32 位 Windows 上运行?我的 PC 如何知道我正在运行 64 位程序?该程序是否有一段代码告诉 Windows 它是一个 64 位程序,还是 Windows 根本无法执行它?
我发现同一个程序的两个版本的文件大小有明显差异,所以我认为是代码不同。是否可以修改代码并使程序运行?
答案1
免责声明:我这辈子从来没有写过操作系统。最好等更有能力的人来回答,然后读一些OSDev文章同时。
该程序是否有一段代码告诉 Windows 它是一个 64 位程序,或者 Windows 根本无法执行它?
两者都有。
所有 Windows 可执行文件(.exe、.dll 等 - 一般为 PE 可执行文件)都有一个标头,告知操作系统它们是为哪种体系结构编译的。它可能是 Intel x86(16 位或 32 位)或 x86_64 或 Itanium 或 Alpha AXP……
如果操作系统在标头中发现不兼容的体系结构,它将完全拒绝运行该程序。在其他情况下 - 例如,如果您尝试在 x86_64 上运行 x86 程序 - 它会知道该程序需要以与其他程序不同的模式运行。
另一方面,程序内部的实际机器代码指令是不同的。(顺便说一句,这就是拥有不同架构的全部意义所在。)64 位 x86_64 架构比 32 位 x86 架构拥有更多指令,而 32 位 x86 架构比 16 位架构拥有更多指令。(而 Alpha、ARM 或 Itanium 等架构之间的差异如此之大,以至于几乎没有什么可以进行比较。)
(即使不同的 x86 CPU 也有不同的指令集——随着时间的推移,它们在基本指令集之上积累了几十个扩展,例如“SSE”或“MMX”或“AES-NI”指令集,因此如果允许编译器针对最新的 CPU 进行优化,程序有可能无法在奔腾等旧 CPU 上运行。)
即使对于两种架构中相同的基本指令,数据大小也可能更大,最重要的是内存地址更大 - 64 位架构通常被称为“64 位”,因为它们使用 64 位来表示内存中的位置,等等。
因此,即使你手动编辑标题以告诉操作系统不同的架构,你最终也只会得到一个每次都会崩溃的程序。
另一方面,x86_64 仍然具有与 x86 相同的指令(它只是添加更多64 位模式下,操作系统运行 32 位程序相对容易;它主要只是在处理该程序时注意只使用 x86 功能。但是,反之则不然——即使 32 位操作系统被编写为将 CPU 切换到 64 位模式以处理您的程序,然后再切换回来,程序仍然很容易执行操作系统无法处理的操作。
如果您有源代码,您可以轻松地为不同的架构进行编译(假设它是正确编写的 - 某些程序仍然有假设,例如内存指针始终为 32 位宽...)但如果您只有一个编译的二进制文件,你就倒霉了。
答案2
在这种情况下,位数是指计算机使用的内存地址的大小。
32 位内存地址系统可以指向最多 2^32(4294967296)个不同的内存位置(正好是 4GB 的存储空间),而 64 位内存地址系统可以指向最多 2^64 个位置(~16 万亿 GB)。
为什么 64 位程序不能在 32 位 Windows 上运行?
32 位程序会以 32 位格式存储其存储数据的各个位置。由于可以将 32 位数据存储在 64 位存储空间中,因此 Windows 会顺利运行该程序,同时适当填充 64 位存储空间中的其他 32 位数据。
另一方面,64 位程序使用 64 位来指示位置。由于不可能在 32 位存储中存储 64 位而不丢弃一半,因此 Windows 将拒绝在 32 位计算机上运行 64 位程序。
该程序是否有一段代码告诉 Windows 它是一个 64 位程序,或者 Windows 根本无法执行它?
每个程序都有一个标头,它告诉 Windows 有关如何运行该程序所需要知道的一切,包括它是 32 位应用程序还是 64 位应用程序。
我发现同一个程序的两个版本的文件大小有明显差异,所以我认为是代码不同。是否可以修改代码并使程序运行?
64 位占用的内存是 32 位的两倍。这就是 64 位程序比 32 位程序大的原因。
这些内存位置仅构成程序的一小部分;大部分是指令(大小保持不变)以及文本和图标等内容。由于只有内存位置的大小翻倍,因此程序的 64 位版本仅比大小翻倍略大。
希望这可以帮助。
答案3
实际上,32位和64位可执行文件之间有两个主要区别。大小和速度。
64 位,访问更多内存
32 位意味着程序的地址空间范围为 2^32 个整数值。这意味着程序只能知道如何计数到 2^32;因此它只能引用该范围内的内存。这大约是 ~2GB。
- 32 位程序最多可以使用 ~4GB 内存。实际上,实际内存要小于这个数字,因为其中一部分内存是为操作系统/代码保留的。
因为 2^64 是一个大得多的数字,所以很明显 64 位程序可以访问更大范围的值;它们可以看到/使用更多的内存。大到您可能不知道 SI 前缀:16 艾字节。艾字节是什么?大到没有人真正关心可预见的未来。
- 64 位程序可以(实际上)引用它所需要的所有内存(在本十年内)。
32 位,占用内存略少,运行速度略快
因此,所有软件都应该针对 64 位进行编译,这似乎很明显。这基本正确,但有一点除外:32 位比 64 位占用的空间更少。这有两个主要后果:
- 64位程序占用更多空间。每个内存引用(指针)占用两倍大小。这种差异通常可以忽略不计。
- 64位程序运行速度稍微慢一些。由于指针较大,内存中的数据就不那么紧密地堆积在一起;机器中各级缓存中填充的数据较少,导致缓存未命中次数增多。如今,良好的缓存利用率(内存局部性)对于性能软件至关重要,因为潜伏。另外,一些算术运算所需的时间与整数的位宽成正比;一些 CPU 指令在 64 位上比在 32 位上要慢。