Составители:
Рубрика:
bne.un.s loop_body [1]
ldloc.0 [2]
stloc.1 [2]
leave.s exit [3]
}
catch System.IndexOutOfRangeException {
pop [2]
ldc.i4.m1 [2]
stloc.1 [2]
leave.s exit [3]
}
exit: ldloc.1 [2]
ret [4]
}
Метод find выполняет поиск элемента k в массиве X. Если элемент
найден, то возвращается его индекс. В противном случае возвращается -1.
В листинге программы справа от каждой инструкции в квадратных скобках
приведен тип передачи управления от нее на следующую инструкцию.
Схема представления кода в виде линейной последовательности ин-
струкций типична для ассемблерных языков и является наиболее ком-
пактной. Действительно, бoльшая часть кода метода состоит из линейных
последовательностей инструкций с неявной передачей управления, а так
как неявная передача определяется порядком следования инструкций и
не требует дополнительного кодирования, то код занимает меньше места.
Некоторые метаинструменты, выполняющие только анализ CIL-ко-
да, могут непосредственно работать с линейной последовательностью ин-
струкций. Это JIT-компиляторы, интерпретаторы, верификаторы и отлад-
чики. Но для метаинструментов, которые выполняют преобразование CIL-
кода, такое представление неудобно, так как при попытке вставить новую
инструкцию в последовательность или удалить инструкцию из последова-
тельности необходимо корректировать адреса во всех инструкциях перехо-
да и во всех описателях блоков обработки исключений. Этих проблем мож-
но избежать, если вместо линейной последовательности инструкций ис-
пользовать представление CIL-кода в виде графа потока управления.
4.1.1. Основные элементы графа потока управления
Граф потока управления – это ориентированный граф, узлы которого
соответствуют инструкциям CIL, а дуги изображают передачу управления
между инструкциями.
В качестве примера рассмотрим фрагмент программы на CIL:
.method private static void print(int32[] X) {
.locals init (int32 i)
Анализ кода на CIL
133
Глава 4. Анализ кода на CIL
4.1. Граф потока управления
Код метода в сборке .NET представляет собой линейную последова-
тельность CIL-инструкций и массив описателей блоков обработки исклю-
чений. Так как представленный в теле метода алгоритм в общем случае
нелинейный, то есть содержит ветвления и циклы, то кодирование его в
виде линейной последовательности требует определения семантики пере-
дачи управления от одной инструкции CIL к другой. Можно выделить че-
тыре механизма передачи управления между инструкциями:
1. Явная передача управления с помощью инструкции перехода.
При этом в параметре инструкции перехода указано относи-
тельное смещение инструкции, на которую будет передано уп-
равление.
2. Неявная (или естественная) передача управления на следующую
инструкцию в последовательности.
3. Передача управления на обработчик исключения при выходе (нор-
мальном или аварийном) из защищенного блока. При такой пе-
редаче управления просматривается массив описателей блоков
обработки исключений до нахождения первого подходящего
блока, из описателя этого блока берется адрес обработчика и
осуществляется переход на инструкцию по этому адресу.
4. Передача управления между методами.
В качестве примера рассмотрим фрагмент программы на языке CIL:
.method private static int32 find(int32[] X, int32 k) {
.locals init (int32 i, int32 result)
.try {
ldc.i4.0 [2]
stloc.0 [2]
br.s loop_cond [1]
loop_body: ldloc.0 [2]
ldc.i4.1 [2]
add [2]
stloc.0 [2]
loop_cond: ldarg.0 [2]
ldloc.0 [2]
ldelem.i4 [2]
ldarg.1 [2]
132
CIL и системное программирование в Microsoft .NET
132 CIL и системное программирование в Microsoft .NET Анализ кода на CIL 133
bne.un.s loop_body [1]
Глава 4. Анализ кода на CIL ldloc.0 [2]
stloc.1 [2]
leave.s exit [3]
}
4.1. Граф потока управления catch System.IndexOutOfRangeException {
pop [2]
Код метода в сборке .NET представляет собой линейную последова- ldc.i4.m1 [2]
тельность CIL-инструкций и массив описателей блоков обработки исклю- stloc.1 [2]
чений. Так как представленный в теле метода алгоритм в общем случае leave.s exit [3]
нелинейный, то есть содержит ветвления и циклы, то кодирование его в }
виде линейной последовательности требует определения семантики пере- exit: ldloc.1 [2]
дачи управления от одной инструкции CIL к другой. Можно выделить че- ret [4]
тыре механизма передачи управления между инструкциями: }
1. Явная передача управления с помощью инструкции перехода. Метод find выполняет поиск элемента k в массиве X. Если элемент
При этом в параметре инструкции перехода указано относи- найден, то возвращается его индекс. В противном случае возвращается -1.
тельное смещение инструкции, на которую будет передано уп- В листинге программы справа от каждой инструкции в квадратных скобках
равление. приведен тип передачи управления от нее на следующую инструкцию.
2. Неявная (или естественная) передача управления на следующую Схема представления кода в виде линейной последовательности ин-
инструкцию в последовательности. струкций типична для ассемблерных языков и является наиболее ком-
3. Передача управления на обработчик исключения при выходе (нор- пактной. Действительно, бoльшая часть кода метода состоит из линейных
мальном или аварийном) из защищенного блока. При такой пе- последовательностей инструкций с неявной передачей управления, а так
редаче управления просматривается массив описателей блоков как неявная передача определяется порядком следования инструкций и
обработки исключений до нахождения первого подходящего не требует дополнительного кодирования, то код занимает меньше места.
блока, из описателя этого блока берется адрес обработчика и Некоторые метаинструменты, выполняющие только анализ CIL-ко-
осуществляется переход на инструкцию по этому адресу. да, могут непосредственно работать с линейной последовательностью ин-
4. Передача управления между методами. струкций. Это JIT-компиляторы, интерпретаторы, верификаторы и отлад-
В качестве примера рассмотрим фрагмент программы на языке CIL: чики. Но для метаинструментов, которые выполняют преобразование CIL-
.method private static int32 find(int32[] X, int32 k) { кода, такое представление неудобно, так как при попытке вставить новую
.locals init (int32 i, int32 result) инструкцию в последовательность или удалить инструкцию из последова-
.try { тельности необходимо корректировать адреса во всех инструкциях перехо-
ldc.i4.0 [2] да и во всех описателях блоков обработки исключений. Этих проблем мож-
stloc.0 [2] но избежать, если вместо линейной последовательности инструкций ис-
br.s loop_cond [1] пользовать представление CIL-кода в виде графа потока управления.
loop_body: ldloc.0 [2]
ldc.i4.1 [2] 4.1.1. Основные элементы графа потока управления
add [2] Граф потока управления – это ориентированный граф, узлы которого
stloc.0 [2] соответствуют инструкциям CIL, а дуги изображают передачу управления
loop_cond: ldarg.0 [2] между инструкциями.
ldloc.0 [2] В качестве примера рассмотрим фрагмент программы на CIL:
ldelem.i4 [2] .method private static void print(int32[] X) {
ldarg.1 [2] .locals init (int32 i)
Страницы
- « первая
- ‹ предыдущая
- …
- 71
- 72
- 73
- 74
- 75
- …
- следующая ›
- последняя »
