Как узнать IL на CLR
Поскольку эти IL кодируют то, что я вижу больше, мне нравится научиться правильно их интерпретировать.
Я не мог найти документацию, такую как компилятор С# или любой другой, поэтому я думаю, что могу позаботиться обо всем остальном после того, как узнаю эти общие:
Ниже приведены некоторые примеры IL-кодов, содержащие то, что мне нужно знать:
Пример 1:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 15 (0xf)
.maxstack 1
.locals init ([0] class EnumReflection.DerivedClass derivedClass)
IL_0000: nop
IL_0001: newobj instance void EnumReflection.DerivedClass::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance void EnumReflection.DerivedClass::WriteOutput()
IL_000d: nop
IL_000e: ret
} // end of method Program::Main
Пример 2:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 38 (0x26)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldstr "Hello"
IL_0006: stfld string EnumReflection.DerivedClass::hello
IL_000b: ldarg.0
IL_000c: ldstr "World"
IL_0011: stfld string EnumReflection.DerivedClass::world
IL_0016: ldarg.0
IL_0017: ldc.i4.s 123
IL_0019: stfld int32 EnumReflection.DerivedClass::age
IL_001e: ldarg.0
IL_001f: call instance void EnumReflection.BaseClass::.ctor()
IL_0024: nop
IL_0025: ret
} // end of method DerivedClass::.ctor
Я знаю, что делают эти коды с тех пор, как я их создал:-) Однако я хотел бы узнать больше о соответствующем IL-коде.
Эти образцы содержат IL-коды, такие как , и не могли бы вы объяснить команду с вопросительными знаками? а также что означают эти команды? Поэтому мы можем легко запомнить их.
- nop (для отладки - нет операции)
- newobj (кажется, он создает новый объект в куче)
- stloc.0?
- ldloc.0?
- ret?
- ldarg.0?
- ldstr?
- stfld?
- ldc.i4.s?
- .ctor - конструктор
Понимание ИЛ важно, поскольку оно раскрывает, как конкретный компилятор создает коды и действует в определенных случаях.
Тем не менее, я не мог найти хорошие документы, содержащие примеры и IL. CLR с С# 3.0 - хорошая книга, но в конечном итоге это не книга IL, поэтому она не объясняет все об ИЛ.
EDIT:
Я нашел спецификации, и они сообщают следующее: Благодаря @usr.
- nop (для отладки - нет операции)
- newobj - создать новый объект
- stloc.0 - значение pop из стека в локальную переменную
- ldloc.0? - загрузить локальную переменную в стек
- ret - возврат из метода
- ldarg.0 - Загрузить аргумент 0 в стек.
- ldstr - загрузить литеральную строку
- stfld - сохранить в поле объекта
- ldc.i4.s - Нажимаем num в стек как int32, короткая форма.
- .ctor - конструктор
Ответы
Ответ 1
Microsoft стандартизировала среду CLR и опубликовала эти стандарты. Раздел III содержит информацию о IL/CIL и подходит для обучения. Это отличный документ.
Вы также можете узнать IL на примере. Скомпилируйте несколько простых методов на С# и посмотрите на IL в отражателе (он имеет IL-режим).
Ответ 2
Есть несколько книг, которые охватывают IL:
Также некоторые книги по обратной инженерии имеют разделы на ИЛ.
См. также:
Ответ 3
- nop - no-op
- newobj - создать объект и вызвать его конструктор.
- stloc.0 - вывести значение из стека и сохранить его в первой локальной переменной
- ldloc.0 - Нажмите первую локальную переменную в стек
- ret - return
- ldarg.0 - Нажмите первый аргумент (
this
в методах экземпляра) в стек
- ldstr - вставьте строку в стек
- stfld - установите поле, используя данные в стеке.
- ldc.i4.s - Нажмите указанный номер как int.
- .ctor - конструктор
Я рекомендую вам найти хороший источник документации по этим опкодам (Wikipedia может быть лучшим, хотя:(). Документация для System.Reflection.Emit содержит довольно подробную документацию для кодов операций.
И, прежде всего, создавайте небольшие программы и изучайте вывод IL. Это лучший способ узнать.
Ответ 4
Если вам нужен краткий обзор каждого кода операции, вы можете сделать хуже, чем проверить пространство имен System.Reflection.Emit
.
Например, существует класс OpCodes
, который имеет статическое поле для каждого кода операции. Затем каждый из них описывается более подробно с точки зрения поведения его стека. Например. Ldarg_0
:
Команда ldarg.0 выталкивает аргумент, индексированный в 0, в стек оценки. Команда ldarg.0 может использоваться для загрузки значения типа или примитивного значения в стек путем копирования его из входящего аргумента.