如何编写 MSIL 或 CIL 并将其编译为可执行文件?

How can I write and compile MSIL or CIL into an executable?

我目前正在研究一些 MSIL/CIL 代码,我正在尝试编译一个用 MSIL 编写的基本 Hello World。但是我遇到了一些麻烦。

起初我 read this article. Then I put the code in the article within an file and use this Stack Overflow answer 作为参考如何使用 ilasm.exe 和 PEVerify.exe 以使该代码成为可执行文件。

这是我的开头:

.method static void main()
{
    .entrypoint
    .maxstack 1

    ldstr "Hello world!"
    call void [mscorlib]System.Console::WriteLine(string)

    ret
}

ilasm.exe 生成可执行文件,但是当我 运行 PEVerify 我得到这个输出:

PS C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools> .\PEVerify.exe /MD /IL C:\clr_code\hello_world_cil.exe

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The module 'C:\clr_code\hello_world_cil.exe' was expected to contain an assembly manifest.
1 Error(s) Verifying C:\clr_code\hello_world_cil.exe

我已经搜索过此错误,但只找到有关使用反射动态代码生成的参考资料,但没有帮助。

然后我决定在 Visual Studio 中构建一个简单的 hello world 控制台应用程序并使用 dotPeek 获取 IL 代码。然后我更改了 hello world 消息并尝试编译输出,这是我使用的代码:

.class private auto ansi beforefieldinit
  HelloMSILV472.Program
    extends [mscorlib]System.Object
{

  .method private hidebysig static void
    Main(
      string[] args
    ) cil managed
  {
    .entrypoint
    .maxstack 8

    // [6 9 - 6 10]
    IL_0000: nop

    // [7 13 - 7 53]
    IL_0001: ldstr        "Hello MSIL!"
    IL_0006: call         void [mscorlib]System.Console::WriteLine(string)
    IL_000b: nop

    // [8 13 - 8 35]
    IL_000c: call         int32 [mscorlib]System.Console::Read()
    IL_0011: pop

    // [9 9 - 9 10]
    IL_0012: ret

  } // end of method Program::Main

  .method public hidebysig specialname rtspecialname instance void
    .ctor() cil managed
  {
    .maxstack 8

    IL_0000: ldarg.0      // this
    IL_0001: call         instance void [mscorlib]System.Object::.ctor()
    IL_0006: nop
    IL_0007: ret

  } // end of method Program::.ctor
} // end of class HelloMSILV472.Program

但是我遇到了同样的错误。我还不知道 .NET Framework IL 和 .NET Core IL 之间是否存在差异,以及目标框架是否影响 ilasm.exe 处理代码的方式,所以我尝试了 .NET Framework 应用程序的输出 IL 和.NET Core 应用程序的输出 IL。但是我遇到了同样的错误。

我如何使用 Notepad++ 之类的东西从头开始构建 MSIL/CIL 基本的 hello world 控制台应用程序,然后编译它并获得 运行ning 可执行文件?

您的初始示例很好 - 您只需通过将此行放在顶部来为您的代码声明一个程序集:

.assembly MyTestAssembly {}

此外,您应该引用您的代码所依赖的任何外部程序集。在这种情况下,因为它只是 mscorlibilasm 会在显示警告后找到它,所以不是强制性的,但它是强制性的,以便调用其他自定义代码:

.assembly extern mscorlib {}

最终代码:

.assembly extern mscorlib {}
.assembly MyTestAssembly {}
.method static void main()
{
    .entrypoint
    .maxstack 1

    ldstr "Hello world!"
    call void [mscorlib]System.Console::WriteLine(string)

    ret
}