【问题标题】:Are 32-bit software builds typically 64-bit optimized? [closed]32 位软件构建通常是 64 位优化的吗? [关闭]
【发布时间】:2013-03-28 09:55:19
【问题描述】:

编辑:刚刚发现(感谢 Ben Voigt 迅速指出)这个提议甚至是不可能的。对于后人来说,这是一个基本问题,而不是我之前对 AMD 扩展的误解:

我一直想知道 32 位构建(尤其是 Windows)软件检测 64 位处理器的存在并利用 64 位操作数和更大的寄存器文件(如果存在)是否很常见。这是假设 32 位进程实际上可以使用 64 位指令,其方式与 i386 上的 16 位进程在物理上存在这样的 CPU 时可以使用 32 位指令的方式大致相同,通过编码覆盖前缀。但是,正如下面的答案所指出的那样,这是不可能的。

为什么要使用 64 位指令而不是 32 位寻址?

好吧,假设您知道您正在处理的数据集足够小以适合该地址空间。例如,您使用了 64 位版本的程序,而对于您使用它的目的,性能监控会告诉您该进程正在使用 2GB 或更少。 (实际上,根据this,设置了 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志的 32 位进程将在 64 位 Windows 中获得 4GB 用户空间。)

有些人认为这无关紧要,但实际上可能。在 64 位构建中,如果我没记错的话,程序存储的每个指针都会消耗它需要的物理 RAM 的两倍!如果程序使用大量指针(例如,由于链表或哈希表),这可能会累加并降低缓存效率等。

不幸的是,正如下面 Ben Voigt 的回答所指出的,这在 Windows 中根本不可能,而专门用于此目的的模式已在 Linux 中完成。

【问题讨论】:

  • 32 位构建的全部意义在于使其能够在 32 位机器上运行。在 32b 机器上,您可以处理 4GB RAM,比目前市场上可用的内存要少得多,即使对于笔记本电脑来说,4GB 也不再多。所以你的指针示例完全没有意义(双关语)
  • 为什么在没有 cmets 的情况下,这被否决了?我也可能是错的,但我觉得这是一个很好的问题,即使 OP 认为这是一个有效的问题是错误的,不是吗?
  • @Sten 是的,RAM 很便宜,但是如果一个进程使用大量的 64 位指针,而 32 位指针可以做到这一点,那么这仍然是低效的,并且可能会通过增加缓存未命中来影响性能。这对于计算密集型进程(如光线追踪器)可能很重要,因为 CPU 缓存大小仍然是一个重大限制。 (@adam 谢谢!)
  • @Kevin 如果代码如此重要,为什么不把它写成汇编并编译 64 位 - 这样你就可以有一个 8 位指针,如果你愿意

标签: windows 64-bit 32bit-64bit


【解决方案1】:

事实上,严格来说,一个程序是 32 位还是 64 位图像只决定了它的寻址模式,而不是它使用的 CPU 功能,包括数据字大小(除非 API/库调用期望给定大小。)

不,这是不正确的。在 Windows 中,32 位与 64 位是两种受支持的英特尔架构和指令集的同义词。 (是的,还支持其他架构——Alpha、Itanium、ARM——但这些总是明确说明的。)

像您描述的二进制文件将是“x86_64 架构,微型内存模型”(通常简称为x32),其中微型内存模型意味着指针小于系统字长,并且数据和代码共享相同的地址空间。 People have made Linux systems like this.

它与“32 位”x86 代码完全不兼容。 x86 指令甚至没有额外寄存器的编码。 CPU 的模式位必须设置不同以支持 x86_64 指令。这与 16 位内存模型时代存在的“基于寻址”和相对指针的概念非常相似。

x32 代码使用 x86_64 指令,并使用处理 32 位数据的指令来访问和执行指针计算。这是通过将虚拟地址限制在范围 (-2GB:+2GB) 的虚拟内存逻辑实现的,因此与将 32 位变量加载到 64 位寄存器相关联的正常符号扩展会创建有效的 64 位指针。

当 CPU 处于“长模式”以支持指令访问额外寄存器时,它无法正确解码 x86 指令。例如,0100 0000 在 x86 中是 ADD 指令,但在 x86_64 中是 MOV。

总之,在分配器的帮助下,64 位代码可以使用 32 位指针。不能将附加寄存器的使用混合到 32 位代码中。

【讨论】:

  • 好吧,回到 i386,在 16 位 TSS 中,操作数自动为 8 位或 16 位,或者在 32 位 TSS 中为 8 位或 32 位 - 但是 ,您可以在指令上附加一个前缀,将编码切换到 8 位或 32 位操作数之间。如果我理解正确,x86-64 架构没有任何等效的方法来覆盖进程模式所隐含的操作数大小 - 对吗?
  • @Kevin:x86_64 有许多不同操作数大小的说明。但是你不能只是将 x86_64 编码的指令混合到 x86 代码中,你需要将处理器置于长模式。
  • 刚刚翻了 AMD64 架构程序员手册,我明白你现在在说什么了。即使在长模式下的兼容模式下,前缀也不适用于 64 位操作数。每天都学点东西!感谢您的快速回复,感谢您的澄清。
  • 0100 0000 是 x86_64 中的 REX 前缀,而不是任何指令。前缀编码为0100WRXB。在 x86 中,它是 incdec,而不是 add
【解决方案2】:

要使用 x64 功能,您需要在 64 位模式下运行。您不能在 32 位进程中使用 64 位寄存器。 32 位进程仅限于 32 位 x86 操作码。您不能使用 32 位进程中的任何 x64 功能。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 2013-08-27
  • 2016-07-03
  • 2018-03-27
  • 2013-07-06
相关资源
最近更新 更多