简答:这是一个完全基于底层数据总线宽度的约定
n 位程序是针对 n 位 CPU优化的程序。否则,64 位程序 是用于 64 位 CPU 的二进制程序 compiled。反过来,64 位 CPU是利用 64 位数据总线在 CPU 和内存之间交换数据的 CPU。
这很简单,但您可以在下面阅读更多内容。
该定义实际上重定向到理解什么是 32/64 位 CPU,间接理解什么是 32/64 位操作系统,以及编译器如何针对给定架构优化二进制文件。
优化 这里包含了二进制本身的格式。给定操作系统的 32 位和 64 位二进制文件,例如Windows 二进制文件,具有不同的格式。但是,给定的 64 位操作系统,例如Windows 64,将能够读取和启动为 32 位版本和 32 位宽数据总线编写的 32 位二进制文件。
32/64 位 CPU,第一个定义
CPU 可以在单个指令中在内存中存储/调用一定数量的数据。 32 位 CPU 一次可以传输 4 个字节(32 位),64 位 CPU 一次可以传输 8 个字节(64 位)。所以“32/64位”前缀来自于在单个读/写周期中传输的RAM数量。
这个数量会影响执行时间:需要的传输周期越少,CPU 等待内存的时间越少,程序执行速度就越快。这就像用一个小桶或一个大桶装大量的水一样。
桶的大小(用于数据传输的位数)用于指示架构的效率,因此对于相同的 CPU,32 位应用程序的效率低于 64 位应用程序。
32/64位CPU,技术定义
显然,RAM 和 CPU 都必须能够管理 32/64 位数据传输,这反过来又决定了用于将 CPU 连接到 RAM 的线数 (system bus)。 32/64 位实际上是构成数据总线的线数/磁道数(通常称为总线“宽度”)。
(维基百科:System bus - 数据总线宽度决定了 CPU、程序、操作系统……的前缀 32/64 位)
(另外一种总线是地址总线,通常比较宽,但是地址总线的宽度与将CPU命名为32位还是64位CPU无关。这个地址总线的宽度决定了总的数量CPU 可以访问/“寻址”的 RAM,例如 2 GB 或 32 GB。至于 控制总线,它是一个小型总线,用于同步连接到数据总线的所有内容,特别是,它表示数据总线何时稳定并准备好在数据传输操作中进行采样)。
在 CPU 和 RAM 之间传输位时,在读取总线上的数据之前,数据总线不同铜轨上的电压必须稳定,否则会出现一个或多个位值错误。 8位稳定所需时间比64位要短,因此增加数据总线宽度并非没有问题要解决。
32/64 位程序:编译器问题
程序并不总是需要传输 4 字节(32 位数据总线)或 8 字节(64 位数据总线),因此它们使用不同的指令来读取 1 字节、2 字节、4 字节和 8 位,出于性能原因。
二进制文件(本机汇编语言程序)的编写要么考虑到 32 位架构,要么考虑到 64 位架构和相关的指令集。所以命名为 32/64 位程序。
目标架构的选择取决于将源程序转换为二进制文件时使用的编译器/编译器选项。大多数编译器都能够从同一源程序生成 32 位或 64 位二进制文件。这就是为什么您在下载首选程序或工具时会同时找到一个应用程序的两个版本的原因。
但是,大多数程序依赖于其他程序员编写的现成库(例如,视频编辑程序可能使用 FFmpeg 库)。要生成一个完全 64 位的应用程序,编译器(实际上是链接编辑器,但让我们保持简单)需要访问所使用的任何库的 64 位版本,这可能是不可能的。
这也适用于操作系统本身,因为操作系统只是一套单独的程序和库。然而,操作系统本身就是一种用户程序的大库,出于效率和安全原因,充当计算机硬件和用户程序之间的网关。操作系统编写汽车的方式阻止了用户程序访问底层 CPU 架构的全部潜力。
32 位程序与 64 位 CPU 的兼容性
64 位操作系统能够在 64 位架构上运行 32 位二进制文件,因为 64 位 CPU 指令集是复古兼容的。但是,需要进行一些调整。
除了数据总线宽度和读/写指令子集之外,32 位和 64 位 CPU 之间还有许多其他差异(寄存器操作、内存缓存、数据对齐/边界、时序......)。
在 64 位架构上运行 32 位程序:
- 比在旧的 32 位架构上运行效率更高(几乎完全是因为与旧的 32/64 位 CPU 相比 CPU 时钟速度有所提高)
- 与运行编译成 64 位二进制文件以利用 64 位体系结构的相同应用程序相比,效率要低,尤其是一次从/向内存传输 64 位的能力。
将源代码编译为 32 位二进制文件时,编译器仍将使用小存储桶,而不是 64 位数据总线可用的较大存储桶。与编译为使用大型存储桶的同一应用程序相比,这对执行速度的影响最大。
关于信息,编译成 16 位 Windows 二进制文件(在具有 16 位数据总线的 80-286 CPU 上运行的早期版本的 Windows)不再完全受支持,尽管在 Windows 10 上仍有可能激活NTVDM.
.NET、Java等解释“字节码”的案例
虽然直到最近几年,编译器都被用来将源程序(例如 C++ 源)翻译成机器语言程序,但这种方法现在处于回归状态。
主要问题是某些 CPU 的机器语言与其他 CPU 的机器语言不同(想想使用 ARM chip 的智能手机和使用 Intel chip 的服务器之间的差异)。您绝对不能在两个硬件上使用相同的二进制文件,它们使用的语言不同,即使有可能,由于它们的工作方式存在巨大差异,两台机器上的效率也会很低。
当前的想法是使用从源代码派生的指令的中间表示 (IR)。 Java(Sun,遗憾的是现在是 Oracle)和 IL(Microsoft)就是这样的中间表示。相同的 IR 文件可以在任何支持 IR 的操作系统上使用。
一旦操作系统打开文件,它会执行最终编译为实际 CPU 可以理解的“本地”机器语言,并考虑运行程序的最终架构。例如,对于 Microsoft .NET,通用版本由位于最终计算机上的 CoreCLR 虚拟机执行。在这种中间语言中通常没有数据总线宽度的概念,因此越来越少的应用程序会有这个 n 位前缀。
但是我们不能忘记实际的架构,所以仍然会有32 and 64 bit versions produced for the CoreCLR 来优化最终代码,即使应用程序本身在 IR 级别上没有针对给定架构进行优化(只有一个 IR 版本可供下载并安装)。