Jump to content

Общий промежуточный язык

Common Intermediate Language ( CIL ), ранее называвшийся Microsoft Intermediate Language ( MSIL ) или Intermediate Language ( IL ), [1] — это набор двоичных команд промежуточного языка , определенный в спецификации Common Language Infrastructure (CLI). [2] Инструкции CIL выполняются CIL-совместимой средой выполнения, такой как Common Language Runtime . Языки, ориентированные на CLI, компилируются в CIL. CIL — это объектно-ориентированный байт на основе стека -код . Среды выполнения обычно по принципу «точно в срок» компилируют CIL-инструкции в собственный код .

Первоначально CIL был известен как Microsoft Intermediate Language (MSIL) во время бета-выпусков языков .NET. Благодаря стандартизации C# и CLI байт-код теперь официально известен как CIL. [3] В определениях вирусов Защитника Windows двоичные файлы, скомпилированные с его помощью, продолжают называться MSIL. [4]

Общая информация [ править ]

Во время компиляции языков программирования CLI исходный код преобразуется в код CIL, а не в объектный код, специфичный для платформы или процессора . CIL — это независимый от процессора и платформы набор инструкций, который может выполняться в любой среде, поддерживающей Common Language Infrastructure, например, в среде выполнения .NET в Windows или в кроссплатформенной среде выполнения Mono . Теоретически это избавляет от необходимости распространять разные исполняемые файлы для разных платформ и типов процессоров. Код CIL проверяется на безопасность во время выполнения, обеспечивая лучшую безопасность и надежность, чем исполняемые файлы, скомпилированные в собственном коде. [5] [6]

Процесс выполнения выглядит следующим образом:

  1. Исходный код преобразуется в байт-код CIL и сборка CLI . создается
  2. При выполнении сборки CIL ее код передается через JIT-компилятор среды выполнения для создания собственного кода. Также можно использовать предварительную компиляцию, которая исключает этот шаг, но за счет переносимости исполняемого файла.
  3. Процессор компьютера выполняет собственный код.

Инструкция [ править ]

Байт-код CIL содержит инструкции для следующих групп задач:

Вычислительная модель [ править ]

Common Intermediate Language является объектно-ориентированным и основанным на стеке , что означает, что параметры и результаты инструкций хранятся в одном стеке, а не в нескольких регистрах или других местах памяти, как в большинстве языков программирования .

Код, добавляющий два числа на языке ассемблера x86 , где eax и edx указывают два разных регистра общего назначения :

add eax, edx

Код на промежуточном языке (IL), где 0 — eax, а 1 — edx:

ldloc.0    // push local variable 0 onto stack
ldloc.1    // push local variable 1 onto stack
add        // pop and add the top two stack items then push the result onto the stack
stloc.0    // pop and store the top stack item to local variable 0

В последнем примере значения двух регистров, eax и edx, сначала помещаются в стек. Когда вызывается инструкция добавления, операнды «извлекаются» или извлекаются, а результат «помещается» или сохраняется в стеке. Полученное значение затем извлекается из стека и сохраняется в eax.

Объектно-ориентированные концепции [ править ]

CIL спроектирован как объектно-ориентированный. Вы можете создавать объекты, вызывать методы и использовать другие типы членов, например поля.

Каждый метод должен (за некоторыми исключениями) находиться в классе. То же самое делает этот статический метод:

.class public Foo {
    .method public static int32 Add(int32, int32) cil managed {
        .maxstack 2
        ldarg.0 // load the first argument;
        ldarg.1 // load the second argument;
        add     // add them;
        ret     // return the result;
    }
}

Метод Add не требует объявления какого-либо экземпляра Foo, поскольку он объявлен как статический, и затем его можно использовать в C# следующим образом:

int r = Foo.Add(2, 3);    // 5

В CIL это будет выглядеть так:

ldc.i4.2
ldc.i4.3
call int32 Foo::Add(int32, int32)
stloc.0

Классы экземпляров [ править ]

Класс экземпляра содержит по крайней мере один конструктор и несколько членов экземпляра . Следующий класс имеет набор методов, представляющих действия объекта Car.

.class public Car {
    .method public specialname rtspecialname instance void .ctor(int32, int32) cil managed {
        /* Constructor */
    }

    .method public void Move(int32) cil managed { /* Omitting implementation */ }
    .method public void TurnRight() cil managed { /* Omitting implementation */ }
    .method public void TurnLeft() cil managed { /* Omitting implementation */ }
    .method public void Brake() cil managed { /* Omitting implementation */ }
}

Создание объектов [ править ]

В C# экземпляры классов создаются следующим образом:

Car myCar = new Car(1, 4); 
Car yourCar = new Car(1, 3);

И эти утверждения примерно такие же, как и эти инструкции в CIL:

ldc.i4.1
ldc.i4.4
newobj instance void Car::.ctor(int, int)
stloc.0    // myCar = new Car(1, 4);
ldc.i4.1
ldc.i4.3
newobj instance void Car::.ctor(int, int)
stloc.1    // yourCar = new Car(1, 3);

Вызов методов экземпляра [ править ]

Методы экземпляра вызываются в C# следующим образом:

myCar.Move(3);

Как вызывается в CIL:

ldloc.0    // Load the object "myCar" on the stack
ldc.i4.3
call instance void Car::Move(int32)

Метаданные [ править ]

Common Language Infrastructure (CLI) записывает информацию о скомпилированных классах в виде метаданных . Подобно библиотеке типов в объектной модели компонентов , это позволяет приложениям поддерживать и обнаруживать интерфейсы, классы, типы, методы и поля в сборке. Процесс чтения таких метаданных называется « отражением ».

Метаданные могут представлять собой данные в форме «атрибутов». Атрибуты можно настроить, расширив Attribute сорт. Это мощная функция. Это дает создателю класса возможность дополнить его дополнительной информацией, которую потребители класса могут использовать различными значимыми способами, в зависимости от предметной области приложения.

Пример [ править ]

Ниже приведен базовый текст «Hello, World!» программа, написанная на ассемблере CIL. Он отобразит строку «Привет, мир!».

.assembly Hello {}
.assembly extern mscorlib {}
.method static void Main()
{
    .entrypoint
    .maxstack 1
    ldstr "Hello, world!"
    call void [mscorlib]System.Console::WriteLine(string)
    ret
}

Следующий код более сложен по количеству кодов операций.

Этот код также можно сравнить с соответствующим кодом в статье про байт-код Java .

static void Main(string[] args)
{
    for (int i = 2; i < 1000; i++)
    {
        for (int j = 2; j < i; j++)
        {
             if (i % j == 0)
                 goto outer;
        }
        Console.WriteLine(i);
        outer:;
    }
}

В синтаксисе ассемблера CIL это выглядит так:

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack  2
    .locals init (int32 V_0,
                  int32 V_1)

              ldc.i4.2
              stloc.0
              br.s       IL_001f
    IL_0004:  ldc.i4.2
              stloc.1
              br.s       IL_0011
    IL_0008:  ldloc.0
              ldloc.1
              rem
              brfalse.s  IL_001b
              ldloc.1
              ldc.i4.1
              add
              stloc.1
    IL_0011:  ldloc.1
              ldloc.0
              blt.s      IL_0008
              ldloc.0
              call       void [mscorlib]System.Console::WriteLine(int32)
    IL_001b:  ldloc.0
              ldc.i4.1
              add
              stloc.0
    IL_001f:  ldloc.0
              ldc.i4     0x3e8
              blt.s      IL_0004
              ret
}

Это всего лишь представление того, как CIL выглядит на уровне виртуальной машины (VM). При компиляции методы сохраняются в таблицах, а инструкции сохраняются в виде байтов внутри сборки, которая представляет собой переносимый исполняемый файл (PE).

Поколение [ править ]

Сборка CIL и инструкции генерируются либо компилятором, либо утилитой, называемой IL Assembler ( ILAsm ), которая поставляется со средой выполнения.

Собранный CIL также можно снова дизассемблировать в код с помощью дизассемблера IL (ILDASM). Существуют и другие инструменты, такие как .NET Reflector , которые могут декомпилировать CIL в язык высокого уровня (например, C# или Visual Basic ). Это делает CIL очень легкой целью для обратного проектирования. Эта черта является общей для байт-кода Java . Однако существуют инструменты, которые могут запутать код и сделать это так, что код не может быть легко читаемым, но при этом остается работоспособным.

Исполнение [ править ]

Сборка точно в срок [ править ]

Компиляция «точно в срок» (JIT) включает в себя преобразование байт-кода в код, который немедленно исполняется процессором. Преобразование выполняется постепенно во время выполнения программы. JIT-компиляция обеспечивает оптимизацию для конкретной среды, безопасность типов во время выполнения и проверку сборки. Для этого JIT-компилятор проверяет метаданные сборки на предмет несанкционированного доступа и соответствующим образом обрабатывает нарушения.

Предварительная компиляция [ править ]

Среды выполнения, совместимые с CLI, также имеют возможность выполнять предварительную компиляцию (AOT) сборки, чтобы ускорить ее выполнение за счет удаления процесса JIT во время выполнения.

В .NET Framework есть специальный инструмент под названием Native Image Generator (NGEN), который выполняет AOT. Другой подход к AOT — CoreRT , который позволяет компилировать код .Net Core в один исполняемый файл без зависимости от среды выполнения. В Mono также есть возможность выполнить AOT.

Инструкции указателя — C++/CLI [ править ]

Заметным отличием от байт-кода Java является то, что CIL поставляется с ldind, stind, ldlocaи множество инструкций вызова, которых достаточно для манипулирования указателями данных/функций, необходимых для компиляции кода C/C++ в CIL.

class A {
   public: virtual void __stdcall meth() {}
};
void test_pointer_operations(int param) {
	int k = 0;
	int * ptr = &k;
	*ptr = 1;
	ptr = &param;
	*ptr = 2;
	A a;
	A * ptra = &a;
	ptra->meth();
}

Соответствующий код в CIL можно отобразить следующим образом:

.method assembly static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) 
        test_pointer_operations(int32 param) cil managed
{
  .vtentry 1 : 1
  // Code size       44 (0x2c)
  .maxstack  2
  .locals ([0] int32* ptr,
           [1] valuetype A* V_1,
           [2] valuetype A* a,
           [3] int32 k)
// k = 0;
  IL_0000:  ldc.i4.0 
  IL_0001:  stloc.3
// ptr = &k;
  IL_0002:  ldloca.s   k // load local's address instruction
  IL_0004:  stloc.0
// *ptr = 1;
  IL_0005:  ldloc.0
  IL_0006:  ldc.i4.1
  IL_0007:  stind.i4 // indirection instruction
// ptr = &param
  IL_0008:  ldarga.s   param // load parameter's address instruction
  IL_000a:  stloc.0
// *ptr = 2
  IL_000b:  ldloc.0
  IL_000c:  ldc.i4.2
  IL_000d:  stind.i4
// a = new A;
  IL_000e:  ldloca.s   a
  IL_0010:  call       valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.CallConvThiscall) 'A.{ctor}'(valuetype A* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst))
  IL_0015:  pop
// ptra = &a;
  IL_0016:  ldloca.s   a
  IL_0018:  stloc.1
// ptra->meth();
  IL_0019:  ldloc.1
  IL_001a:  dup
  IL_001b:  ldind.i4 // reading the VMT for virtual call
  IL_001c:  ldind.i4
  IL_001d:  calli      unmanaged stdcall void modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall)(native int)
  IL_0022:  ret
} // end of method 'Global Functions'::test_pointer_operations

См. также [ править ]

Ссылки [ править ]

  1. ^ «Промежуточный язык и исполнение» .
  2. ^ «Инфраструктура общего языка ECMA-335 (CLI)» .
  3. ^ «Что такое промежуточный язык (IL)/MSIL/CIL в .NET» . Проверено 17 февраля 2011 г. CIL: ...Когда мы компилируем [a]. NET, он [преобразовывается] не напрямую в двоичный код, а в промежуточный язык. При запуске проекта каждый язык программирования .NET преобразуется в двоичный код CIL. Только некоторая часть CIL, необходимая во время выполнения, преобразуется в двоичный код. DLL и EXE .NET также находятся в форме CIL.
  4. ^ «HackTool:MSIL/SkypeCracker» . Майкрософт . Проверено 26 ноября 2019 г. .
  5. ^ Троэльсен, Эндрю (2 мая 2009 г.). Преимущества CIL . ISBN  9781590598849 . Проверено 17 февраля 2011 г.
  6. ^ «Неуправляемые и управляемые расширения для C++, управляемых и .Net Framework» . www.visualcplusdotnet.com . Проверено 7 июля 2020 г.

Дальнейшее чтение [ править ]

  • Бок, Джейсон (2002). CIL-программирование: под капотом .NET . Апресс. ISBN  978-1590590416 .

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 871b3589753e282b4ca7c3512972ea06__1714304220
URL1:https://arc.ask3.ru/arc/aa/87/06/871b3589753e282b4ca7c3512972ea06.html
Заголовок, (Title) документа по адресу, URL1:
Common Intermediate Language - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)