Введение в MSIL - Часть 1: Hello World — Архив WASM.RU

Все статьи

Введение в MSIL - Часть 1: Hello World — Архив WASM.RU

Описывая C++/CLI и его связь с C#, мне часто хочется обсудить Microsoft intermediate language (MSIL), генерируемые компиляторами Visual C++ и Visual C#. Проблема состоит в то, что большинство программистов не знакомы с MSIL и такие программы как ILDASM не слишком полезны для новичка, потому что отображаемые ими MSIL для него не читаем. Поэтому я решил написать несколько статей, рассказывающие о MSIL на вводном уровне. Так как я сильно сомневаюсь, что после их прочтения кто-то действительно пойдёт и начнёт писать код на MSIL, я пропущу некоторые неинтересные детали и сфокусируюсь на таких вещах, как определение типов, написание методов, инструкции вызова и обработка исключений.

Давайте начнём с простой стартовой функции, которая отображает очень неожиданное сообщение. В отличии от C#, CLI не требует, чтобы метод принадлежал к какому-либо классу. Стартовая функция также не обязательно должна называться 'main', но для упрощение я использовал именно это имя.

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

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

    ret
}

Метод main называется определением метода, так как и сигнатура и тело метода наличествуют. Когда же есть только сигнатура без тела, это называется объявлением метода. Последние обычно используются как цели вызова (когда метод вызывается), в то время как определение метода предоставляет конкретную его реализацию.

Определение метода начинается с директивы .method и может находится в зоне глобальной видимости или внутри класса. Стартовая функция приложения должна быть статической. Объявление глобального метода статическим может показаться избыточным, но компилятор ILASM в некоторых случаях жалуется, если вы опускаете ключевое слово static.

Директива .entrypoint указывает, что этот метод является стартовым для приложения. Только в одном методе приложения может быть такая директива.

Директива .maxstack говорит, сколько слотов в стеке предположительно будет использовано. Например, сложение двух чисел потребует поместить два числа в стек и вызвать инструкцию add, которая возьмёт сверху эти два числа и положит обратно результат. В этом случае вам понадобится два стековых слота.

Инструкция ldstr помещает строку, которая должна быть передана методу WriteLine, в стек. Инструкция call вызывает статический метод WriteLine класса System.Console из сборки mscorlib. Это пример объявления метода, с полный сигнатурой метода WriteLine (включая строковый аргумент), чтобы среда выполнения могла определить, какую конкретно перегрузку метода необходимо вызвать.

И наконец, инструкция ret возвращеет управление вызывающему. В случае стартовой функции это означает конец выполнения приложения.

2002-2013 (c) wasm.ru