Эта статья требует дополнительных ссылок для проверки . ( ноябрь 2017 г. ) ( Узнайте, как и когда удалить это сообщение-шаблон ) |
Общий промежуточный язык ( CIL ), ранее называвшийся Microsoft Intermediate Language ( MSIL ) или Intermediate Language ( IL ), [1] - это набор двоичных инструкций промежуточного языка, определенный в спецификации Common Language Infrastructure (CLI). [2] Инструкции CIL выполняются CLI-совместимой средой выполнения, такой как Common Language Runtime . Языки, предназначенные для компиляции CLI в CIL. КСС является объектно-ориентированным , стековый байт - код . Время выполнения обычно точно в сроккомпилировать инструкции CIL в машинный код .
CIL был первоначально известен как Microsoft Intermediate Language (MSIL) во время бета-версий языков .NET. Благодаря стандартизации C # и CLI байт-код теперь официально известен как CIL. [3] В описаниях вирусов Защитника Windows двоичные файлы, скомпилированные с его помощью, по-прежнему называются MSIL. [4]
Общая информация [ править ]
Во время компиляции CLI языков программирования , то исходный код преобразуется в CIL код , а не в процессор или от платформы специфичного кода объекта . CIL - это не зависящий от процессора и платформы набор инструкций, который может выполняться в любой среде, поддерживающей инфраструктуру общего языка, например в среде выполнения .NET в Windows или кроссплатформенной среде выполнения Mono . Теоретически это избавляет от необходимости распространять разные исполняемые файлы для разных платформ и типов ЦП. Код CIL проверяется на безопасность во время выполнения, обеспечивая лучшую безопасность и надежность, чем исполняемые файлы, скомпилированные в собственном коде. [5] [6]
Процесс выполнения выглядит так:
- Исходный код преобразуется в байт-код CIL и создается сборка CLI .
- После выполнения сборки CIL ее код передается через JIT-компилятор среды выполнения для генерации собственного кода. Также может использоваться предварительная компиляция, которая исключает этот шаг, но за счет переносимости исполняемого файла.
- Процессор компьютера выполняет собственный код.
Инструкции [ править ]
Байт-код CIL содержит инструкции для следующих групп задач:
- Загрузить и сохранить
- Арифметика
- Преобразование типов
- Создание и манипулирование объектами
- Управление стеком операндов (push / pop)
- Передача управления (разветвление)
- Вызов и возврат метода
- Выбрасывание исключений
- Мониторинг параллелизма
- Манипуляции с указателями данных и функций, необходимые для C ++ / CLI и небезопасного кода C #
Вычислительная модель [ править ]
Общий промежуточный язык является объектно-ориентированным и основанным на стеке , что означает, что параметры инструкций и результаты хранятся в одном стеке, а не в нескольких регистрах или других местах памяти, как в большинстве языков программирования .
Код, который добавляет два числа на языке ассемблера x86 , где eax и edx указывают два разных регистра общего назначения :
добавить eax , edx
Код на промежуточном языке (IL), где 0 - это eax, а 1 - это edx:
ldloc . 0 // помещаем локальную переменную 0 в стек ldloc . 1 // помещаем локальную переменную 1 в стек add // pop и добавляем два верхних элемента стека, затем помещаем результат в стек stloc . 0 // извлекаем и сохраняем верхний элемент стека в локальную переменную 0
В последнем примере значения двух регистров, eax и edx, сначала помещаются в стек. Когда вызывается инструкция добавления, операнды «выталкиваются» или извлекаются, а результат «помещается» или сохраняется в стеке. Полученное значение затем извлекается из стека и сохраняется в eax.
Объектно-ориентированные концепции [ править ]
CIL разработан как объектно-ориентированный. Вы можете создавать объекты, вызывать методы и использовать другие типы членов, например поля.
Каждый метод должен (за некоторыми исключениями) находиться в классе. Так делает этот статический метод:
. class public Foo { . метод public static int32 Add ( int32 , int32 ) cil managed { . maxstack 2 ldarg . 0 // загружаем первый аргумент; ldarg . 1 // загружаем второй аргумент; добавить // добавить их; ret // вернуть результат; } }
Метод Add не требует объявления какого-либо экземпляра Foo, потому что он объявлен как статический, и затем его можно использовать в C # следующим образом:
int r = Foo . Добавить ( 2 , 3 ); // 5
В CIL это будет выглядеть так:
ldc . i4 . 2 ЖК . i4 . 3 вызовите int32 Foo :: Add ( int32 , int32 ) stloc . 0
Классы экземпляров [ править ]
Класс экземпляра содержит по крайней мере один конструктор и несколько членов экземпляра . В следующем классе есть набор методов, представляющих действия объекта Car.
. class public Car { . Метод общественного specialname rtspecialname инстанции недействительным . ctor ( int32 , int32 ) cil managed { / * Конструктор * / } . method public void Move ( int32 ) cil managed { / * Опускается реализация * / } . method public void TurnRight () cil managed { / * Без реализации * / } . method public void TurnLeft () cil managed { / * Без реализации * / } . method public void Brake () cil managed { / * Пропуск реализации * / } }
Создание объектов [ править ]
В C # экземпляры классов создаются так:
Автомобиль myCar = новый Автомобиль ( 1 , 4 ); Автомобиль yourCar = новый Автомобиль ( 1 , 3 );
И эти инструкции примерно такие же, как эти инструкции в CIL:
ldc . i4 . 1 ЖК . i4 . 4 экземпляра newobj void Car ::. т е р ( INT , INT ) stloc . 0 // myCar = new Car (1, 4); ldc . i4 . 1 ЖК . i4 . 3 экземпляра newobj void Car ::. т е р ( INT , INT ) stloc . 1 // yourCar = new Car (1, 3);
Вызов методов экземпляра [ править ]
Методы экземпляра вызываются в C # как следующие:
myCar . Двигаться ( 3 );
Как вызывается в CIL:
ldloc . 0 // Загружаем объект myCar в стек ldc . i4 . 3 вызов экземпляра void Car :: Move ( int32 )
Метаданные [ править ]
Common Language Infrastructure (CLI) записывает информацию о скомпилированных классов как метаданные . Подобно библиотеке типов в объектной модели компонентов , это позволяет приложениям поддерживать и обнаруживать интерфейсы, классы, типы, методы и поля в сборке. Процесс чтения таких метаданных называется « отражением ».
Метаданные могут быть данными в форме «атрибутов». Атрибуты можно настроить, расширив Attribute
класс. Это мощная функция. Это дает создателю класса возможность украсить его дополнительной информацией, которую потребители класса могут использовать различными значимыми способами в зависимости от домена приложения.
Пример [ править ]
Ниже представлена базовая программа Hello, World, написанная на CIL. Будет отображена строка «Hello, world!».
. сборка Привет {} . сборка extern mscorlib {} . метод static void Main () { . точка входа . maxstack 1 ldstr "Привет, мир!" называют недействительным [ mscorlib ] System . Console :: 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 ) goto outer ; } Консоль . WriteLine ( i ); внешний:; } }
В синтаксисе CIL это выглядит так:
. метод private hidebysig static void Main ( string [] args ) cil managed { . точка входа . maxstack 2 . местные инициализации ( int32 v_0 , int32 v_1 ) ldc . i4 .2 stloc .0 br . s IL_001f IL_0004 : ldc . i4 0,2 stloc 0,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 blt . s IL_0004 ret }
Это просто представление того, как CIL выглядит на уровне виртуальной машины (ВМ). При компиляции методы сохраняются в таблицах, а инструкции хранятся в байтах внутри сборки, которая является переносимым исполняемым файлом (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 * ptra = & a a; птра -> мет (); }
Соответствующий код в CIL можно представить следующим образом:
. метод сборки static void modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvCdecl ) test_pointer_operations ( int32 param ) cil managed { . vtentry 1 : 1 // Размер кода 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 // загрузить локальную адресную инструкцию IL_0004 : stloc .0 // * ptr = 1; IL_0005 : ldloc .0 IL_0006 : ldc . i4 .1 IL_0007 : stind . i4 // косвенная инструкция // ptr = & param IL_0008 : ldarga . s param // команда загрузки адреса параметра 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 IL_0010 : вызов ValueType * modopt ([ mscorlib ] System . Runtime . CompilerServices . CallConvThiscall ) ' A. { ctor } ' ( valuetype A * modopt ([ mscorlib ] System . Runtime . CompilerServices . IsConst ) modopt ([ mscorlib ] System . Runtime . CompilerServices . IsConst ) ) IL_0015 : поп// ptra = & a; IL_0016 : ldloca . s a IL_0018 : stloc .1 // ptra-> meth (); IL_0019 : ldloc .1 IL_001a : dup IL_001b : ldind . i4 // чтение VMT для виртуального вызова IL_001c : ldind . i4 IL_001d : каллусы неуправляемого STDCALL недействительный modopt ([ mscorlib ] System . Время воспроизведение . CompilerServices .CallConvStdcall ) ( native int ) IL_0022 : ret } // конец метода 'Global Functions' :: test_pointer_operations
См. Также [ править ]
- Список инструкций CIL
- Список языков интерфейса командной строки
Ссылки [ править ]
- ^ «Промежуточный язык и исполнение» .
- ^ "Инфраструктура общего языка ECMA-335 (CLI)" (PDF) . п. 32.
- ^ «Что такое промежуточный язык (IL) / MSIL / CIL в .NET» . Проверено 17 февраля 2011 .
CIL: ... Когда мы компилируем [a].
NET, он [преобразуется] не напрямую в двоичный код, а в промежуточный язык.
При запуске проекта все языки программирования .NET преобразуются в двоичный код в CIL.
Только некоторая часть CIL, которая требуется во время выполнения, преобразуется в двоичный код.
DLL и EXE в .NET также находятся в форме CIL.
- ^ "HackTool: MSIL / SkypeCracker" . Microsoft . Проверено 26 ноября 2019 года .
- ^ Троелсен, Эндрю (2009-05-02). Преимущества CIL . ISBN 9781590598849. Проверено 17 февраля 2011 .
- ^ «Неуправляемые, управляемые расширения для C ++, Managed и .Net Framework» . www.visualcplusdotnet.com . Проверено 7 июля 2020 .
Дальнейшее чтение [ править ]
- Бок, Джейсон (2002). Программирование на CIL: под капотом .NET . Апресс. ISBN 978-1590590416.
Внешние ссылки [ править ]
- Инфраструктура общего языка (стандарт ECMA-335)
- «Стандарты ECMA C # и общеязыковой инфраструктуры» на веб-сайте Visual Studio.
- Программа Hello World в CIL
- Скорость: NGen повышает вашу производительность с помощью новых мощных функций - MSDN Magazine, апрель 2005 г.