手写一个建议的IL反汇编器(1)

要想反汇编一个方法,必须首先找到这个方法,然后将这个方法的IL提取出来。

提取string.IsNullOrEmpty方法的IL

 

下面演示如何提取string.IsNullOrEmpty方法的IL。

        public static void Main() {

            //第一步,获取IsNullOrEmpty方法

            MethodInfo isNullOrEmptyMethod = typeof(string).GetMethod("IsNullOrEmpty");



            //第二步,获取IsNullOrEmpty方法体

            MethodBody methodBody = isNullOrEmptyMethod.GetMethodBody();



            //第三步,获取IL

            byte[] ilBytes = methodBody.GetILAsByteArray();



            //以十六进制形式输出IL

            Console.Write(BitConverter.ToString(ilBytes));



            Console.Read();

 

编译,运行。你会惊讶的发现,区区4行代码就提取出了一个方法的IL。

 

解码IL

首先定义一个字典,用于映射指令码,如下:

 

  public struct OpCodeInfo {

        public string Name;

        public Int32 OperandSize;

        public OpCodeInfo(string name, Int32 operandSize) {

            this.Name = name;

            this.OperandSize = operandSize;

        }

    }



    public class OpcodeList {

        private static Dictionary<int,OpCodeInfo> s_opcodes;



        public static Dictionary<int, OpCodeInfo> OpCodes{

            get{

                if(s_opcodes==null){

                    s_opcodes= new Dictionary<int, OpCodeInfo>(){      

                    {0x2,new OpCodeInfo("ldarg.0",0)},

                    {0x2c,new OpCodeInfo("brfalse.s",1)},

                    {0x6f,new OpCodeInfo("callvirt",4)},

                    {0x16,new OpCodeInfo("ldc.i4.0",0)},

                    {0xFE01,new OpCodeInfo("ceq",0)},

                    {0x2A,new OpCodeInfo("ret",0)},

                    {0x17,new OpCodeInfo("ldc.i4.1",0)}};

                }

                

                return s_opcodes;

            }

        }

    }

 

这里为了简单,只针对IsNullOrEmpty中的每一个指令码进行了映射。

 

紧接着,遍历IL指令流,读取指令。

    

            for(int i = 0; i < ilBytes.Length; i++) {

                //如果指令码的第一个字节等于0xFE,就说明这个指令的指令码是两字节

                if(ilBytes[i] == 0xFE) {

                    //获取双字节指令码

                    int twoByteCodes = (ilBytes[i] << 8) | ilBytes[++i];



                    //解析指令码

                    OpCodeInfo opcode = OpcodeList.OpCodes[twoByteCodes];



                    //输出指令码

                    Console.Write(opcode.Name);



                    //输出指令码的操作数

                    for(int j = 0; j < opcode.OperandSize; j++) {

                        Console.WriteLine("{0} ", ilBytes[j]);

                    }



                    //移动到下一个IL指令

                    i += opcode.OperandSize;



                    //换行

                    Console.WriteLine();



                } else {

                    //获取指令码,这里是一字节指令

                    OpCodeInfo opcode = OpcodeList.OpCodes[ilBytes[i]];



                    //输出指令码

                    Console.Write(opcode.Name);



                    //输出指令码对应的操作数

                    for(int j = 0; j < opcode.OperandSize; j++) {

                        Console.Write("{0} ", ilBytes[j]);

                    }



                    //移动到下一个指令

                    i += opcode.OperandSize;



                    Console.WriteLine();

                }

            }

 

现在,运行,输出效果如下:

 

 手写一个建议的IL反汇编器(1)

 

 

你可能感兴趣的:(汇编)