为什么32位代码不能使用64位共享库?

为什么32位代码不能使用64位共享库?

在GNU/Linux、x86/x86-64上,一般来说,(至少有时,也许有例外)64位库代码不能被32位程序使用的原因是什么?

我知道 x86-64 和 x86、长模式、扩展寄存器、新寄存器、段的删除(在某种程度上)之间的许多差异。

但这为什么重要呢?长模式中与特权代码相关的更改不适用于系统库,除非它们在内核模式下运行,而内核模式则不然。

至于用户土地的变化、更大的寄存器、新的寄存器等,为什么这很重要?在 64 位系统上,CPU 在进入用户空间时已经在长模式下运行,并且长模式在这种情况下向后兼容(甚至无需切换到保护模式),它应该能够使用 32 位模式位和 64 位代码,位于用户空间。

我在这里遗漏了一些明显的东西吗?

当然,现在,如果 64 位库只是具有不同的 API,或者只是具有不同的名称,例如运行ldd可能会显示它正在寻找与 32 位等效库具有不同名称的共享库。那将是一个问题。尽管如果这就是全部的话,解决方案(即使是拼凑的)将非常容易。

我还可以想象,由于 x86-64 调用约定与常规 x86 不同,因此即使调用库中的函数也会出现问题。这肯定是问题的一部分吗?

但感觉这里应该有更好的理由,而且我确信我错过了一些明显的东西。

答案1

x86-64 处理器只能通过其实现的兼容模式向后兼容 32 位 x86 处理器。长模式下 x86-64 的大多数指令与 ia-32 指令相同,因此您可以通过(除其他外)忽略寄存器的上半部分来实现某些兼容性。但是,也存在差异,一些 ia-32 指令(例如短跳转)已从 x86-64 长模式中删除。 64 位和 32 位 x86 有效地实现了不同的指令集。

通过将处理器切换到兼容模式,您只能在 x86-64 CPU 上运行 32 位代码,反之亦然。要从 32 位兼容模式调用 64 位库代码,需要从兼容模式切换到 64 位长模式。这需要为长模式和兼容模式下的代码设置单独的代码段,因为模式是由代码段描述符中的一位确定的。还有一些事情需要考虑,例如,在兼容模式下,CPU 只能看到较低的 4 GB 虚拟地址空间。

相关内容