是否可以通过模式切换在 64 位进程中执行 32 位代码?

Posted

技术标签:

【中文标题】是否可以通过模式切换在 64 位进程中执行 32 位代码?【英文标题】:Is it possible to execute 32-bit code in 64-bit process by doing mode-switching? 【发布时间】:2011-07-02 03:49:03 【问题描述】:

在此页面中,http://www.x86-64.org/pipermail/discuss/2004-August/005020.html 他说有一种方法可以在应用程序中混合 32 位代码和 64 位代码。他假设应用程序是 32 位的(在兼容模式下),然后切换到 64 位模式以执行 64 位代码,反之亦然。

假设我的操作系统是 64 位 linux,而我的应用程序是 64 位。我做了一个很远的跳转来切换到兼容模式并执行 32 位代码。当我进行系统调用或函数调用时它可以正常工作吗?

兼容模式和 64 位模式之间的模式切换是否有任何开销?我认为开销之一是我需要单独的 32 位和 64 位堆栈。

我能不能把这个想法集成到JVM中,也许我可以在64位JVM中动态生成32位代码,并通过模式切换来执行?

【问题讨论】:

如果您使用的是 64 位 JVM,为什么要生成 32 位代码?您可以(几乎)在 64 位代码中执行所有您想要的 32 位操作;即使在 64 位模式下,大多数指令也默认使用 32 位操作数。 因为我想比较一下32位代码和64位代码的区别。也许在某些情况下我会有所不同,比如 long 类型的大小,或者每种情况的执行时间。 再次阅读帖子,它建议修改 CS——这将调用自定义 ld.so 和类似的东西。确保您为此做好准备。 【参考方案1】:

开放编码的系统调用应该没问题,因为您的 32 位代码将使用 32 位内核入口点。

当然,只能对其他 32 位代码进行函数调用。这包括libc - 因此您的 32 位代码必须是独立的,或者您必须为其所需的库函数提供 thunk。请记住,通常不会直接调用系统调用 - 您通常会通过 libc 包装器,而您的 32 位代码将无法使用该包装器。

在模式之间切换肯定会产生开销。您应该查阅您的处理器文档以了解它是什么。

【讨论】:

在您看来,我必须准备 2 个不同版本的 libc(32 位和 64 位),但是是否可以将 32 位和 64 位库加载到可执行文件中,甚至使用 dlopen 动态加载?我认为不可能。 @Hsiao-Hui Chiu:不,这通常是不可能的,反正这也不是你想做的。两个不同的libc 意味着两组冲突的 stdio 缓冲区和类似的问题。相反,您需要编写切换回长模式的 32 位 thunk,然后调用 64 位 libc,包括对参数和结果进行必要的改组。

以上是关于是否可以通过模式切换在 64 位进程中执行 32 位代码?的主要内容,如果未能解决你的问题,请参考以下文章

在 64 位 linux 上从 32 位模式切换到 64 位(长模式)

是否可以在支持Intel IA-32e模式的操作系统中运行16位代码?

在 64 位操作系统上,32 位进程可以访问多少内存?

如何使 .NET 可执行文件在 64 位操作系统上作为 32 位进程运行?

如何检查给定地址是 32 位还是 64 位?

我何时需要使用64位Azure函数?