Страницы

Поиск по вопросам

вторник, 9 октября 2018 г.

Как работает метод GetILAsByteArray()?

Метод MethodBody.GetILAsByteArray(); возвращает IL-код в байтовом представлении, сие ясно. Однако я не нашел конкретики в описании работы данного метода на MSDN: возвращает ли он "дословную" инструкцию, которую описывал я, либо же эта функция возвращает именно ту инструкцию, которая будет исполняться?
Поясню:
В Debug-режиме компилятор никак не оптимизирует код, так что исполняемая инструкция идентична той, которую описывал сам программист. В Release-режиме же компилятор инлайнит, упраздняет и в целом меняет многие вещи, так что конечная исполняемая инструкция может серьезно разниться с тем, что изначально описывалось.

Влияет ли как-то на GetILAsByteArray() режим компиляции, или же данный метод всегда возвращает "дословную" инструкцию метода?


Ответ

Влияет ли как-то на GetILAsByteArray() режим компиляции
Ответ - "да". В этом легко убедиться на практике. Напишем тестовый метод:
public void Method(int a, int b) { string str = (a+b).ToString(); MessageBox.Show(str); }
Далее, напишем такой код для извлечения первого операнда из его MSIL-кода и отображения имени операции:
using System; using System.Text; using System.Reflection; using System.Reflection.Emit;
...
var mi = this.GetType().GetMethod("Method"); byte[] msil = mi.GetMethodBody().GetILAsByteArray(); ushort op;
if(msil[0]==0xfe) op = (ushort)(msil[1] | 0xfe00); else op = (ushort)(msil[0]);
//найдем имя операции string str=""; FieldInfo[] mas = typeof(OpCodes).GetFields(); for(int i=0;itextBox1.Text = "0x"+op.ToString("X4")+": "+str;
Результат:
Debug - 0x0000: nop
Release - 0x0003: ldarg.1
Объясняется это тем, что в отладочной сборке в начале каждого метода вставляется пустой оператор для облегчения отладки (чтобы можно было поставить точку останова на самое начало метода, тогда как в релизной сборке можно только на первую строку). Таким образом, режим компиляции действительно влияет на IL-код метода.

Комментариев нет:

Отправить комментарий