【问题标题】:What does it mean for a program to be 32 or 64 bit? [closed]程序是 32 位还是 64 位意味着什么? [关闭]
【发布时间】:2019-10-04 18:23:41
【问题描述】:

这个问题:How many bits does a WORD contain in 32/64 bit OS respectively?,提到字长是指处理器寄存器的位大小——我认为这是指计算机处理器操作的位数/即最小的“不可分割”位数处理器正在运行。

正确吗?使用 Word/Excel/等软件,安装程序可以选择 32 位或 64 位安装。有什么区别?

由于计算机体系结构是固定的,在我看来,“32 位”软件的设计应与具有 32 位体系结构的计算机体系结构保持一致。而 64 位程序会努力将指令集与 64 位字长对齐。

对吗?

这里提出了一个非常相似的问题:From a programming point of view, what does it mean when a program is 32 or 64 bit? - 接受的答案提到区别在于可以分配给应用程序的内存量。但这太模糊了——除非 32 位 / 64 位软件作为一个概念与 32 位 / 64 位字处理器大小完全无关?

【问题讨论】:

  • 架构不固定。大多数 64 位操作系统还可以选择执行 32 位程序。他们提供了一个模拟 32 位操作系统的模拟器。必然如此,如果他们不这样做并强迫客户更新所有这些最喜欢的应用程序,它们就不会很受欢迎。这几乎总是很难注意到,但这样一个程序的开发人员可能会非常关心。因为你可以分配更多的内存。
  • " 计算机处理器操作的位数/即处理器操作的最小“不可分割”位数。"我会说“处理器舒适操作的最小位数”,因为它仍然可以使用 8、16 和 32 位单元。
  • @HansPassant 至少在 Windows 中没有太多的仿真。当进行系统调用时,处理器从传统模式切换到长模式并继续在内核中,就好像什么都没发生过一样。 Translation libraries.
  • 64-bit computing Wikipedia page 有一些很好的信息。
  • X86-64 实际上是将两个(或更多)架构整合到一个包中,因此您可以选择在同一台机器上运行 32 位或 64 位程序。其他拱门不一定是这样。例如 IA64 aka Itanium 不支持运行 32 位程序。

标签: c 32bit-64bit


【解决方案1】:

字的大小是一个主要区别,但不是唯一的区别。它倾向于定义 CPU 的“额定”位数,但字长和整体能力只是松散相关。整体能力才是最重要的。

在 Intel 或 AMD CPU 上,32 位与 64 位软件实际上是指 CPU 运行时的运行模式。 32 位模式有更少/更小的可用寄存器和指令,但最重要的限制是可用内存量。 32 位软件通常限制使用 2GB 到略低于 4GB 的内存

内存的每个字节都有一个唯一的地址,这与每个房子都有一个唯一的邮政地址没有太大区别。内存地址只是一个数字,一旦程序将数据保存到内存中,它就可以使用它来再次查找,并且内存的每个字节都必须有一个地址。如果地址是 32 位,则有 2^32 个可能的地址,这意味着 2^32 个可寻址字节的内存。在当今的 Intel/AMD CPU 上,内存地址的大小与寄存器的大小相同(尽管并非总是如此)。

对于 32 位地址,程序可以寻址 4GB(2^32 字节),但是操作系统保留了多达一半的空间。可用内存空间必须适合程序代码、数据,通常还有被访问的文件。在今天的 PC 中,具有许多 GB 的 RAM,这无法利用可用内存。这就是 64 位变得流行的主要原因。 64 位 CPU 可用并被广泛使用(通常在 32 位模式下)几年,直到大于 2GB 的内存变得普遍,此时 64 位模式开始提供现实世界的优势并变得流行。 64 位内存地址空间提供了 16 EB 的可寻址内存(约 18 万亿字节),这比当前任何软件都可以使用的多,当然没有 PC 有这么多 RAM。

典型应用程序中使用的大部分数据,即使在 64 位模式下,也不需要是 64 位的,因此大部分仍以 32 位(或更小)格式存储。文本的常见 ASCII 和 UTF-8 表示使用 8 位数据格式。如果程序需要在内存中将一大块文本从一个地方移动到另一个地方,它可能会尝试一次执行 64 位,但如果它需要解释文本,它可能会一次执行 8 位.同样,32 位是整数的常见大小(最大范围为 +/- 2^31,或大约 +/- 21 亿)。 21 亿的范围足以满足多种用途。图形数据通常自然是逐像素表示的,每个像素通常最多包含 32 位数据。

不必要地使用 64 位数据有一些缺点。 64 位数据在内存中占用更多空间,在 CPU 缓存中占用更多空间(CPU 用于短期存储的非常快的内存)。内存只能以最大速率传输数据,而 64 位数据是两倍大。如果浪费地使用,这会降低性能。如果需要同时支持 32 位和 64 位版本的软件,则尽可能使用 32 位值可以减少两个版本之间的差异并使开发更容易(但并不总是这样)。

在 32 位之前,地址和字长通常不同(例如 16 位 8086/88 具有 20 位内存地址但 16 位寄存器,或 8 位 6502 具有 16 位内存地址,或甚至早期的具有 26 位地址的 32 位 ARM)。虽然没有程序员对更好的寄存器嗤之以鼻,但内存空间通常是每一代先进技术的真正驱动力。这是因为大多数程序员很少直接使用寄存器,而是直接使用内存,而内存限制直接导致程序员不愉快,在 32 位到 64 位的情况下,用户也会感到不愉快。

总而言之,虽然各种位大小之间存在真正重要的技术差异,但 32 位或 64 位(或 16 位或 8 位)的真正含义意味着倾向于与特定技术世代的 CPU 和/或利用这些功能的软件相关联的功能集合。字长是其中的一部分,但不是唯一的,也不一定是最重要的部分。

来源:在所有这些技术时代都是程序员。

【讨论】:

  • 谢谢 - 这是一个非常详细的答案。当我阅读时,我意识到我实际上并不知道“可寻址内存”是什么意思。这很容易描述吗?
  • @ZachSmith 转到 youtube 并观看 Ben Eater 关于构建 8-bit breadboard CPU 的系列。您的所有问题都会得到解答。
  • 我很失望没有提到 x86 和 x86-64(有时缩写为 x64)指令集。
  • 请注意,32-bit software is generally limited to using 2GB of memory 并不完全正确。在 Windows 上,有 /3GB 引导标志来进行 3/1GB 的拆分。与/LARGEADDRESSAWARE 链接的程序可以在 32/64 位模式下使用 3GB/4GB 内存。默认情况下,Linux 也拆分 3/1GB,尽管您可以切换到 1/3 或 2/2,甚至在以后的内核版本中也可以像 5/8-3/8 这样的小数拆分。此外,Windows 中还有 AWE,允许 32 位进程访问更多内存(但每次仍为 4GB)
  • 我应该知道人们会提出他们试图从 32 位内存空间中挤出最后几个字节的各种方法!还更详细地解释了可寻址内存。
【解决方案2】:

您参考的答案描述了 64 位相对于 32 位的好处。至于程序本身的实际不同之处,取决于您的观点。

一般来说,程序源代码不必完全不同。 Most programs can be written so that they compile perfectly well as either 32-bit or 64-bit programs, as controlled by appropriate choice of compiler and / or compiler options.但是,通常对源代码有一些影响,因为针对 64 位的 (C) 编译器可能会选择以不同方式定义其类型。特别是,long int 在 32 位平台上普遍为 32 位宽,但在许多(但不是全部)64 位平台上为 64 位宽。这可能是导致对此类细节做出无根据假设的代码错误的来源。

主要区别都在二进制文件中。 64 位程序利用其 64 位目标 CPU 的完整指令集,这些指令集总是包含 32 位对应 CPU 不包含的指令。他们将使用 32 位对应 CPU 没有的寄存器。他们将使用适合其目标 CPU 的函数调用约定,这通常意味着在寄存器中传递比 32 位程序更多的参数。使用 64 位 CPU 的这些和其他功能可提供功能优势,例如能够使用更多内存和(有时)提高性能。

【讨论】:

  • 程序源代码不必完全不同 我会注意到它确实假定代码符合 C 标准并且不执行填充指针之类的操作进入int 值或假设size_tunsigned long。我已经修复了许多由此类错误代码引起的错误...
  • @AndrewHenle 因此是“一般来说”限定词。有例外,但它们不会影响大多数程序。
  • @Barmar 不幸的是,根据我的经验,有太多 C 程序员没有意识到“指针实际上只不过是整数”和“变量对齐无关紧要”之类的东西实际上是根据 C 标准不正确。在将“工作”的 32 位代码编译成 64 位可执行文件时,这些东西会引入非常糟糕的错误。
  • @AndrewHenle:不幸的是,我们生活在一个宽松架构(x86、较新版本的 ARM 等)的世界中,它们默默地修复了未对齐的访问。虽然根据规范,未对齐可能是 UB,但只要您不直接别名对齐和未对齐的指针,在没有足够聪明的优化器的情况下,您很有可能侥幸逃脱。显然,它仍然是错误的,但如果它没有在 QA 中崩溃,很多商店还是会发货。
  • x86-64 调用约定更高效的另一个原因是它们是最近设计的,考虑到效率,而不是简单性。在非 Windows 平台上尤其如此,没有人会费心替换 i386 System V 调用(只是将其扩展为 __m128 / __m256 类型),因此它仍然传递堆栈上的所有参数,而不是使用任何寄存器。除了使用gcc -mregparm=3 或其他东西编译的代码,比如 Linux 内核的 32 位版本。因此,一些 32 位代码无法利用其为 arg 传递提供的少数寄存器。
【解决方案3】:

程序运行在由处理器实现的给定架构(arch 或 ISA)之上。通常,体系结构定义了“主”字大小,这是大多数寄存器和这些寄存器上的操作运行的大小(尽管您可以设计以不同方式工作的体系结构)。这通常称为“本机”字长,尽管架构可能允许使用不同大小的寄存器进行操作。

此外,处理器使用内存,并且需要以某种方式寻址该内存——这意味着使用这些地址进行操作。因此,地址通常能够像任何其他数字一样被存储和操作,这意味着您有能够保存它们的寄存器。虽然不需要这些寄存器与字长匹配,也不需要从单个寄存器计算地址,但在某些架构中就是这种情况。

纵观历史,有许多不同字长的架构,甚至是奇怪的架构。如今,您可以很容易地找到您周围的处理器,不仅是 32 位和 64 位,还有例如8 位和 16 位(通常在嵌入式设备中)。在典型的台式计算机中,您使用的是 x86 或 x64,它们分别是 32 位和 64 位。

因此,当您说程序是 32 位或 64 位时,您指的是特定的体系结构。在流行的桌面场景中,您指的是 x86 与 x64。有很多问题、文章和书籍讨论了两者之间的差异。

现在,最后一点:出于兼容性原因,x64 处理器可以在不同的模式下运行,其中一种能够运行来自 x86 的 32 位代码。这意味着如果您的计算机(可能)是 x64 并且您的操作系统支持它(也可能,例如 Windows 64 位),它仍然可以运行为 x86 编译的程序。

【讨论】:

    【解决方案4】:

    使用 Word/Excel/等软件,安装程序可以选择 32 位或 64 位安装。有什么区别?

    这取决于使用的 CPU:

    在 SPARC CPU 上,“32 位”和“64 位”程序之间的区别正是您所想的:

    64 位程序使用 32 位 SPARC CPU 不支持的附加操作。另一方面,Solaris 或 Linux 操作系统将 64 位程序访问的数据放在只能使用 64 位指令访问的内存区域中。这意味着 64 位程序甚至必须使用 32 位 CPU 不支持的指令。

    对于 x86 CPU,这是不同的:

    现代 x86 CPU 具有不同的操作模式,它们可以执行不同类型的代码。在不同的模式下,它们可以执行 16、32 或 64 位代码。

    在 16 位、32 位和 64 位代码中,CPU 对字节的解释不同:

    字节(十六进制)b8 4e 61 bc 00 c3 将被解释为:

    mov    eax,0xbc614e
    ret
    

    ... 在 32 位代码中并作为:

    mov    ax,0x614e
    mov    sp,0xc300
    

    ... 16 位代码。

    “64 位安装”和“32 位安装”的 EXE 文件中的字节必须由 CPU 以不同方式解释。

    64 位程序会努力将指令集与 64 位字长对齐。

    当 CPU 不是 16 位 CPU 时,16 位代码(见上文)可以访问 32 位寄存器。

    因此“16 位程序”可以访问 32 位或 64 位 x86 CPU 上的 32 位寄存器。

    【讨论】:

    【解决方案5】:

    提到字长是指处理器寄存器的位大小

    通常是的(尽管有一些例外/并发症)

    • 我认为这是指计算机处理器运行的位数/即处理器运行的最小“不可分割”位数。

    不,大多数处理器架构都可以处理小于其原生字长的值。更好(但不是完美)的定义是处理器可以(通过主整数数据路径)作为单个单元处理的最大数据。

    一般来说,在现代 32 位和 64 位系统上,指针的大小与字的大小相同,但在许多 64 位系统上,并非所述指针的所有位实际上都是可用的。可以有一个内存模型,其中可寻址内存大于系统的本机字大小,这在 8 位和 16 位时代很常见,但自从引入 32-位 CPU。

    由于计算机架构是固定的

    虽然物理架构当然是固定的,但许多处理器具有多种操作模式,程序员可以使用不同的指令和寄存器。在 64 位模式下,可以使用 CPU 的全部功能,在 32 位模式下,处理器提供向后兼容的接口,限制了功能和地址空间。模式差异很大,必须针对特定模式编译代码。

    作为一般规则,在 64 位模式下运行的操作系统可以支持在 32 位模式下运行的应用程序,但反之则不行。

    因此,32 位应用程序在运行 32 位操作系统的 32 位处理器、运行 32 位操作系统的 64 位处理器或运行 64 位操作系统的 64 位处理器上以 32 位模式运行位操作系统。

    另一方面,64 位应用程序通常只能在运行 64 位操作系统的 64 位处理器上运行。

    【讨论】:

      【解决方案6】:

      您拥有的信息是图片的重要组成部分,但不是全部。我不是处理器专家,所以我的答案可能会遗漏一些细节。

      32 位 vs 64 位与处理器架构有关。字长的增加有几件事情:

      • 更大的字长可以定义更多的指令。例如,执行单个加载指令的 8 位处理器总共只能有 256 条指令,其中较大的字长允许在处理器微代码中定义更多指令。显然,定义了多少真正有用的指令是有限度的。
      • 由于有更多可用位,因此单个指令周期可以处理更多数据。这加快了执行速度。
      • 正如您所说,它还允许访问更大的内存空间,而无需执行多个地址周期或多路复用高/低数据字等操作。

      当处理器架构从 32 位迁移到 64 位时,芯片制造商可能会保持与之前指令集的兼容性,因此之前开发的所有软件仍将在新架构上运行。当您以 64 位架构为目标时,编译器将提供新的指令和内存寻址方案,以更有效地处理数据。

      【讨论】:

      • 字大小与指令大小无关。 x86 有各种可能的指令大小,从 1 到 15 个字节。哈佛体系结构的数据和指令内存的字节大小可能甚至不同。
      • 我不知道任何具有固定大小 64 位指令字的 64 位 CPU 架构。 DEC Alpha(设计于 90 年代初)是 64 位的(不是对现有 ISA 的扩展),但仍然使用 4 字节指令,因为每个简单的 add 指令不需要花费 8 个字节;它是一个 RISC,因此每条指令的复杂性都非常低。您关于更广泛说明的观点仅适用于 8 -> 16 和 16 -> 32 增长; 32 位对于典型的指令来说已经足够了。
      • “一条指令可以处理更多数据”,这仅在程序使用 64 位整数或扩展精度时才有用。否则单个add 仍然只是add。无论模式如何,SIMD 向量寄存器都具有相同的宽度,因此例如,32 位模式下的 x86 CPU 仍然可以使用paddd xmm0, xmm1 进行 4 次打包的 32 位加法。
      • 点了。我职业生涯的大部分时间都是使用 8 到 32 位字长的嵌入式处理器,所以这就是我的观点的来源。
      • 许多现代 32 位和 64 位 RISC 架构具有紧凑的 16 位指令集(RISC-V、MIPS、ARM...),有些具有可变长度指令集(RISC-五、手臂……)
      【解决方案7】:

      简答:这是一个完全基于底层数据总线宽度的约定

      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 版本可供下载并安装)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-19
        • 1970-01-01
        • 2012-03-17
        • 1970-01-01
        • 2011-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多