CIL之——field的存储与加载

来源:互联网 发布:国家网络安全法 解读 编辑:程序博客网 时间:2024/06/03 22:42

field指的是类内部的成员变量,供类内部的方法调用,那在CIL代码中field是如何实现存储与加载的呢?下面让我们一窥究竟。

目标C#代码

先看一段简单的C#代码:

public class Program{    // Fields    private string _timeArea;    // Methods    public string get_TimeArea()    {        // This item is obfuscated and can not be translated.        return this._timeArea;    }    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }    public void set_TimeArea(string value)    {        // This item is obfuscated and can not be translated.        this._timeArea = value;    }}

CIL实现field存储

例一:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public void set_TimeArea(string 'value')//(string val)不用加单引号    {        .maxstack 1        ldarg.0 //本操作码对应this._timeArea=value中的this        ldarg.1 //本操作码对应this._timeArea=value中的value        stfld string GuoNameSpace.Program::_timeArea //本操作码对应this._timeArea=value中的._timeArea        ret    }}

例一解释:

public class Program{    // Fields    private string _timeArea;    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }    public void set_TimeArea(string value)    {        this._timeArea = value;    }}

例二:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public void set_TimeArea(string 'value')//(string val)不用加单引号    {        .maxstack 1        ldarg.0 //本操作码与value._timeArea = "aaa"无关        ldarg.1 //本操作码对应value._timeArea = "aaa"中的value        ldstr "aaa" //本操作码对应value._timeArea = "aaa"中的"aaa"        stfld string GuoNameSpace.Program::_timeArea //本操作码对应value._timeArea = "aaa"中的._timeArea        ret    }}

例二解释:

public class Program{    // Fields    private string _timeArea;    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }    public void set_TimeArea(string value)    {        // This item is obfuscated and can not be translated.        value._timeArea = "aaa";    }}

例三:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public void set_TimeArea(string 'value')//(string val)不用加单引号    {        .maxstack 1        ldarg.0 //本操作码与"aaa"._timeArea = "bbb"无关        ldarg.1 //本操作码与"aaa"._timeArea = "bbb"无关        ldstr "aaa" //本操作码对应"aaa"._timeArea = "bbb"中的"aaa"        ldstr "bbb" //本操作码对应"aaa"._timeArea = "bbb"中的"bbb"        stfld string GuoNameSpace.Program::_timeArea //本操作码对应"aaa"._timeArea = "bbb"中的._timeArea        ret    }}

例三解释:

public class Program{    // Fields    private string _timeArea;    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }    public void set_TimeArea(string value)    {        // This item is obfuscated and can not be translated.        "aaa"._timeArea = "bbb";    }}

经过三个例子的对比发现,存储field时,stfld操作与堆栈顶部的两个值是密切相关的,执行stfld操作时堆栈最顶部的值就是field的值,位于堆栈次顶部的值表示field的所属对象。

CIL实现field加载

例一:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public string get_TimeArea()    {        .maxstack 1        .locals init(            string timeArea        )        ldarg.0 //本操作码对应this._timeArea中的this        ldfld string GuoNameSpace.Program::_timeArea //本操作码对应this._timeArea中的._timeArea        stloc.0        ldloc.0        ret    }}

例一解释:

public class Program{    // Fields    private string _timeArea;    // Methods    public string get_TimeArea()    {        return this._timeArea;    }    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }}

例二:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public string get_TimeArea()    {        .maxstack 1        .locals init(            string timeArea        )        ldarg.0 //本操作码与"aaa"._timeArea无关        ldstr "aaa" //本操作码对应"aaa"._timeArea中的"aaa"        ldfld string GuoNameSpace.Program::_timeArea //本操作码对应"aaa"._timeArea中的._timeArea        stloc.0        ldloc.0        ret    }}

例二解释:

public class Program{    // Fields    private string _timeArea;    // Methods    public string get_TimeArea()    {        return "aaa"._timeArea;    }    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }}

例三:

.class public Program extends [mscorlib]System.Object{    .field private string _timeArea    .method public static void Main()    {        .entrypoint        .maxstack 1        ldstr "Hello"        call void [mscorlib]System.Console::WriteLine(string)        call string [mscorlib]System.Console::ReadLine()        ret    }    .method public string get_TimeArea()    {        .maxstack 1        .locals init(            string timeArea        )        ldarg.0 //本操作码与"bbb"._timeArea无关        ldstr "aaa" //本操作码与"bbb"._timeArea无关        ldstr "bbb" //本操作码对应"bbb"._timeArea中的"aaa"        ldfld string GuoNameSpace.Program::_timeArea //本操作码对应"bbb"._timeArea中的._timeArea        stloc.0        ldloc.0        ret    }}

例三解释:

public class Program{    // Fields    private string _timeArea;    // Methods    public string get_TimeArea()    {        return "bbb"._timeArea;    }    public static void Main()    {        // This item is obfuscated and can not be translated.        Console.WriteLine("Hello");    }}

经过三个例子的对比发现,加载field时,ldfld操作与堆栈最顶部的值是密切相关的,执行ldfld操作时堆栈最顶部的值表示field的所属对象。

翻旧账

不知道大家还记不记得静态方法中只能使用静态字段,为什么不能使用非静态字段呢?是时候解释一下了。
静态方法中ldarg.0表示方法的第一个参数,所以没办法使用ldarg.0来调用this.field;
非静态方法中ldarg.0表示this,所以可以使用ldarg.0来调用this.field。
就这么简单,不知道各位看明白了吗?欢迎各位留言提出宝贵意见。

原创粉丝点击