stringtranslate.com

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

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 указывают два разных регистра общего назначения :

добавить eax , edx  

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

лдлок . 0 // помещаем локальную переменную 0 в стек ldloc . 1 // помещаем локальную переменную 1 в стек add // извлекаем и добавляем два верхних элемента стека, затем помещаем результат в стек stloc . 0 // извлекаем и сохраняем верхний элемент стека в локальную переменную 0    

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

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

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

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

. класс общественный Foo { . метод public static int32 Add ( int32 , int32 ) cil Managed { . maxstack 2 ldarg . 0 // загружаем первый аргумент; лдарг . 1 // загружаем второй аргумент; добавить // добавить их; ret // возвращаем результат; } }                       

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

интервал р = Фу . Добавить ( 2 , 3 ); // 5     

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

ООО . я4 . 2 ЖК . я4 . 3 вызовите int32 Foo :: Добавить ( int32 , int32 ) stloc . 0   

Классы экземпляров

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

. общественный автомобиль класса { . метод public Specialname rtspecialname экземпляр void . ctor ( int32 , int32 ) cil Managed { /* Конструктор */ }                 . метод public void Move ( int32 ) cil Managed { /* Опуская реализацию */ } . метод public void TurnRight () cil Managed { /* Опуская реализацию */ } . метод public void TurnLeft () cil Managed { /* Опуская реализацию */ } . метод public void Brake () cil Managed { /* Пропуск реализации */ } }                                   

Создание объектов

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

Автомобиль myCar = новый автомобиль ( 1 , 4 ); Автомобиль yourCar = новый автомобиль ( 1 , 3 );           

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

ООО . я4 . 1 ЖК . я4 . 4 экземпляра newobj void Car ::. ctor ( int , int ) stloc . 0 // myCar = новый автомобиль(1, 4); ООО . я4 . 1 ЖК . я4 . 3 экземпляра newobj void Car ::. ctor ( int , int ) stloc . 1 // ваша машина = новая машина (1, 3);          

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

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

моя машина . Двигаться ( 3 );

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

лдлок . 0 // Загрузите объект «myCar» в стек ldc . я4 . 3 экземпляра вызова void Car :: Move ( int32 )    

Метаданные

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

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

Пример

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

. сборка Привет {} . сборка extern mscorlib {} . метод static void Main () { . входная точка . maxstack 1 ldstr "Привет, мир!" вызовите void [ mscorlib ] System . Консоль :: WriteLine ( строка ) 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 ) перейти во внешний мир ; } Консоль . WriteLine ( я ); внешний :; } }                                   

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

. метод Privateidebysig статический недействительный Main ( строка [ ] args ) cil управляемый { . входная точка . Максстек 2 . локальные инициализации ( int32 V_0 , int32 V_1 )                  ООО . i4 .2 стлок .0 бр . s IL_001f IL_0004 : ldc . i4 .2 стлок .1 комн . s IL_0011 IL_0008 : ldloc .0 ldloc .1 rem brfalse . s IL_001b ldloc .1 ldc . i4 .1 добавить stloc .1 IL_0011 : ldloc .1 ldloc .0 blt . s IL_0008 ldloc .0 call void [ mscorlib ] System . Консоль :: WriteLine ( int32 ) IL_001b : ldloc .0 ldc . i4.1 добавить stloc.0 IL_001f : ldloc.0 ldc .i4 0x3e8 блт . с IL_0004 в отставку }                                       

Это всего лишь представление того, как 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.

класс A { общественный : виртуальный недействительный __stdcall meth () {} }; void test_pointer_operations ( int param ) { int k = 0 ; int * ptr = & k ; * ПТР = 1 ; ПТР = & параметр ; * ПТР = 2 ; А а ; А * птра = a ; птра -> мет (); }                             

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

. метод сборки static void modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvCdecl ) test_pointer_operations ( int32 param ) cil Managed { . vtentry 1 : 1 // Размер кода 44 (0x2c) . Максстек 2 . locals ([ 0 ] int32 * ptr , [ 1 ] valuetype A * V_1 , [ 2 ] valuetype A * a , [ 3 ] int32 k ) // k = 0; IL_0000 : ЛДК . i4 .0 IL_0001 : stloc .3 // ptr = &k; IL_0002 : ldloca . s k // инструкция загрузки локального адреса IL_0004 : stloc .0 // *ptr = 1; IL_0005 : ldloc.0 IL_0006 : ldc .i4 .1 IL_0007 : стоять . i4 // инструкция косвенного обращения // ptr = ¶m IL_0008 : ldarga . s param // инструкция загрузки адреса параметра IL_000a : stloc .0 // *ptr = 2 IL_000b : ldloc .0 IL_000c : ldc . i4 .2 IL_000d : стоять . i4 // a = новый A; IL_000e : ldloca . s a IL_0010 : вызвать valuetype A * modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvThiscall ) ' A . { ctor } ' ( valuetype A * modopt ([ mscorlib ]                                                                        Система . Время выполнения . Службы компилятора . IsConst ) modopt ([ mscorlib ] System . Runtime . CompilerServices . IsConst )) IL_0015 : pop // ptra = &a; IL_0016 : ldloca . IL_0018 : stloc .1 // ptra->meth() ; IL_0019 : ldloc.1 IL_001a : dup IL_001b : ldind .i4 // чтение VMT для виртуального вызова IL_001c : ldind . i4 IL_001d : calli unmanaged stdcall void modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvStdcall ) ( native int ) IL_0022 : ret } // конец метода «Глобальные функции»::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 г.

дальнейшее чтение

Внешние ссылки