ILバイトコードを取得
ちょっと前にWindows.Formsを見ていくようなことを言っていましたが、GUI関連は画像がない分かり難く日記向けなネタじゃないのであっさり止めて、クラスライブラリ探索にしました。(^^;
今回はリフレクション関連で追加されたMethodBodyを弄ってみました。
#region Using directives using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Reflection.Emit; #endregion namespace ConsoleApplication1 { class Program { static void SayHello(string name) { int a = 10; int b = 20; int c = a + b; Console.WriteLine(c); Console.WriteLine("Hello " + name); } static int GetInt32(byte code, int index) { byte b = new byte[4]; Array.Copy(code, index, b, 0, b.Length); return BitConverter.ToInt32(b, 0); } static void Main(string args) { Type t = typeof(Program); // SayHelloを取得 MethodInfo mi = t.GetMethod("SayHello", BindingFlags.Static | BindingFlags.NonPublic); // MethodyBodyを取得 MethodBody mb = mi.GetMethodBody(); int i = 0; // SayHelloのILバイトコードを取得 byte code = mb.GetILAsByteArray(); // 力業でバイトコードを文字変換(^^; while (i < code.Length) { int op = code[i++]; if (OpCodes.Ldstr.Value == op) { Console.WriteLine("{0}{1:X}", OpCodes.Ldstr.ToString().PadRight(10), GetInt32(code, i)); i += 4; } else if (OpCodes.Call.Value == op) { Console.WriteLine("{0}{1:X}", OpCodes.Call.ToString().PadRight(10), GetInt32(code, i)); i += 4; } else if (OpCodes.Ret.Value == op) Console.WriteLine(OpCodes.Ret); else if (OpCodes.Ldarg_0.Value == op) Console.WriteLine(OpCodes.Ldarg_0); else if (OpCodes.Stloc_0.Value == op) Console.WriteLine(OpCodes.Stloc_0); else if (OpCodes.Stloc_1.Value == op) Console.WriteLine(OpCodes.Stloc_1); else if (OpCodes.Stloc_2.Value == op) Console.WriteLine(OpCodes.Stloc_2); else if (OpCodes.Stloc_1.Value == op) Console.WriteLine(OpCodes.Stloc_1); else if (OpCodes.Ldloc_0.Value == op) Console.WriteLine(OpCodes.Ldloc_0); else if (OpCodes.Ldloc_1.Value == op) Console.WriteLine(OpCodes.Ldloc_1); else if (OpCodes.Ldloc_2.Value == op) Console.WriteLine(OpCodes.Ldloc_2); else if (OpCodes.Add.Value == op) Console.WriteLine(OpCodes.Add); else if (OpCodes.Ldc_I4_S.Value == op) Console.WriteLine("{0}{1}", OpCodes.Ldc_I4_S.ToString().PadRight(10), code[i++]); else Console.WriteLine(op.ToString("X2")); } Console.ReadLine(); } } } /* 結果 ldc.i4.s 10 stloc.0 ldc.i4.s 20 stloc.1 ldloc.0 ldloc.1 add stloc.2 ldloc.2 call A00000F ldstr 70000001 ldarg.0 call A000010 call A000011 ret */
実行時にILコードを持ってこれるのは良いのですが、それを扱うクラスが用意されていないのは辛いですね。自力でちまちまはやりたくない。C#のパーサが相変わらず実装されていないのも合わせて何とかして貰いたいです。(^^;
うーん、bit和演算子の前後にスペース入れないとソースが崩れる・・・