【问题标题】:How does compiling to AnyCPU actually produce executable code?编译到 AnyCPU 是如何实际生成可执行代码的?
【发布时间】:2021-10-15 23:20:45
【问题描述】:

我在编译 .NET 程序时对“AnyCPU”的理解是编译后的 EXE/DLL 应该在 x86 和 x64(以及其他?)CPU 上运行。

我想生成的中间语言被 Just-In-Time 编译器翻译成相关的机器代码,并且 .NET 运行时知道目标 CPU,所以这是有道理的。

我不明白 EXE(以及 JIT 编译器/CLR)实际上是如何启动的;程序的入口点肯定需要存在一些机器代码吗?那么在编译之前不需要知道目标 CPU 架构吗?

[编辑:删除了反汇编代码,因为我查看了错误的地址]

当我最初发布这个问题时,我没有意识到 x86 和 x64 机器代码有多相似,所以我的猜测是生成入口点的代码可以在 x86 和 x64 上工作。

【问题讨论】:

  • 它比看起来要复杂得多,从 32 位 .exe 文件创建 64 位进程需要 significant tricks。这不再那么重要了,当您使用 VS 构建时,.NETCore 需要一个明确的主机,即 dotnet.exe 或 apphost.exe(重命名为项目名称)。主机的选择锁定了位数。
  • 我不太明白你在说什么。首先,我真正感兴趣的案例(这是我在编译时看到的)是一个明显的 64 位 EXE 如何在 32 位机器上运行。其次,如果我双击我的 EXE,无论我是否安装了任何 .NET 框架,它肯定会作为本机 EXE 运行。当然,它稍后会失败,但它会运行得足够远,告诉我我需要这个框架,对吧?

标签: .net windows portable-executable


【解决方案1】:

似乎有一些标志是操作系统在代码执行前检查并决定是否需要返回BadImageFormatException错误或运行程序(基于x86或x64编译方式); Any CPU 选项基本上是一个 32 位编译版本,也可以在 64 位操作系统上轻松运行,因为在 64 位 Windows 系统中,系统 dll 的 32 位和 64 位版本都被存储。 欲了解更多信息,请阅读Dr.Zone page,我在这里引用了其中的一部分:

当使用那种风格的anycpu时,语义如下:

  • 如果进程在 32 位 Windows 系统上运行,它将作为 32 位进程运行。 il 被编译成 x86 机器码。
  • 如果进程在 64 位 Windows 系统上运行,它会作为 32 位进程运行。 il 被编译成 x86 机器码。
  • 如果进程在 arm windows 系统上运行,它将作为 32 位进程运行。 il 被编译为 arm 机器代码。

另请阅读similar question in StackOverflow

【讨论】:

  • "...Any CPU 选项基本上是一个 32 位编译版本,也可以在 64 位操作系统上轻松运行" - 我不认为这是真的,但“AnyCPU”程序从纯粹的“本机”EXE 角度来看,我编译的似乎是 64 位的。我的意思是 PE Optional Header 部分有一个幻数 0x20b,我理解它是位标志,意思是 64 位。
  • 正如我从 msdn 的这句话中理解的那样:anycpu(默认)编译您的程序集以在任何平台上运行。您的应用程序尽可能以 64 位进程运行,并在只有该模式可用时回退到 32 位。 它编译到两种架构并从 x64 开始,如果失败,它会跳转到 32 位部分代码。您应该检查 x64 和 x86 上的任何 cpu 编译的二进制头文件,以确切了解它是如何运行的。 @SamuelB
  • 还有 JIT 编译器的问题,它可以根据需要将代码编译为所需的架构。 AnyCPU 程序集在加载到 64 位进程时将 JIT 到 64 位代码,当加载到 32 位进程时将 JIT 到 32 位代码。也看看这个image
猜你喜欢
  • 2015-02-22
  • 1970-01-01
  • 2020-01-12
  • 2016-09-15
  • 1970-01-01
  • 2012-05-12
  • 2011-04-17
  • 2020-07-23
相关资源
最近更新 更多