Как я могу написать и скомпилировать MSIL или CIL в исполняемый файл? - PullRequest
0 голосов
/ 24 апреля 2020

В настоящее время я изучаю немного кода MSIL / CIL и пытаюсь скомпилировать базовый c Hello World, написанный на MSIL. Однако у меня есть некоторые проблемы.

Сначала я прочитал эту статью . Затем я помещаю код в статье в файл и использую этот ответ переполнения стека в качестве ссылки на то, как использовать 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

I ' я искал эту ошибку, но нашел только ссылки на динамический c код, использующий отражение, что не помогло.

Затем я решил создать простое консольное приложение hello world в Visual Studio и использовал 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 работает с кодом, поэтому я попробовал вывести IL из. NET Рамочное приложение и выходной IL. NET Базового приложения. Однако у меня та же ошибка.

Как я могу с нуля создать консольное приложение MSIL / CIL basi c hello world, используя что-то вроде Notepad ++, а затем скомпилировать его и запустить работающий исполняемый файл?

1 Ответ

0 голосов
/ 28 апреля 2020

Ваш первоначальный пример в порядке - вам просто нужно объявить сборку для вашего кода, поместив эту строку вверху:

.assembly MyTestAssembly {}

Кроме того, вы должны ссылаться на любые внешние сборки, которые ваш код опирается на. В этом случае, поскольку только mscorlib, ilasm найдет его после отображения предупреждения, поэтому не обязательно, но это будет обязательно для вызова другого пользовательского кода:

.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
}
...