• 【.Net底层剖析】2.stfld指令-给对象的字段赋值


    .Net底层剖析目录章节

    1.【深入浅出.Net IL】1.一个For循环引发的IL 

    2.【.Net底层剖析】2.stfld指令-给对象的字段赋值

    3.【.Net底层剖析】3.用IL来理解属性

    引言:

      这篇我们讲解在.net  IL中间语言中,经常见到的指令stfld

      该指令经常用在给一个对象的字段赋值。

     一、指令用途:

      MSDN解释如下:

      Replaces the value stored in the field of an object reference or pointer with a new value.

      翻译过来就是:用一个新值替换对象字段的值

    二、命名空间和程序集

      命名空间是在  System.Reflection.Emit这个里面

      程序集是mscorlib(mscorlib.dll)

     三、指令执行机制

      工作原理即堆栈转换行为如下:

      按照先后顺序:

        1.将一个对象引用或指针压入堆栈

        2.将值被压入堆栈

        3.该值和对象的引用/指针从堆栈中弹出,对象的字段更新为替换的值

    四、 实例代码分析:

    C#程序:

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Test test1=new Test();//new一个Test对象
                test1.i = 12;//将Test对象的字段i赋值为12
            }
    
            /// <summary>
            /// 测试类
            /// </summary>
            public class Test
            {
                public int i = 100;
            }
        }
    }

    IL 程序Main方法

    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       16 (0x10)
      .maxstack  2
      .locals init ([0] class ConsoleApplication1.Program/Test test1)
      IL_0000:  nop
      IL_0001:  newobj     instance void ConsoleApplication1.Program/Test::.ctor()
      IL_0006:  stloc.0
      IL_0007:  ldloc.0
      IL_0008:  ldc.i4.s   12
      IL_000a:  stfld      int32 ConsoleApplication1.Program/Test::i
      IL_000f:  ret
    } // end of method Program::Main

    我们来逐行分析下main方法的IL代码

    .entrypoint  //定义函数的入口点

      // Code size       16 (0x10)//代码大小为16

      .maxstack  2//栈的大小为2

      .locals init ([0] class ConsoleApplication1.Program/Test test1)//定义一个变量为test1,存储在<本地变量列表>中第一个变量中

      IL_0000:  nop//空操作

      IL_0001:  newobj     instance void ConsoleApplication1.Program/Test::.ctor()//new 一个Test对象,一个引用指向这个对象,引用存放在栈上,

    对象存放在堆上面

      IL_0006:  stloc.0//将引用弹栈,存放到<本地变量列表>中的第一个变量中

      IL_0007:  ldloc.0//<本地变量列表>中第一个变量的值压入堆栈

      IL_0008:  ldc.i4.s   12//int 12压入堆栈

      IL_000a:  stfld      int32 ConsoleApplication1.Program/Test::i//将堆栈的栈顶的值赋值给堆栈的第二个值,即test.i=12

      IL_000f:  ret//函数返回

     五、内存分析

    在指令stfld 执行之前的内存图

     

     

    堆栈中存放12test1的地址,<本地变量列表>第一个变量中存放的是test1的地址,堆中存放的是test1指向的一个对象,其中test1.i=100

     

    在指令stfld 执行之后的内存图

     

     

     

     

    堆栈中的12test1的地址弹出,<本地变量列表>第一个变量中存放的是test1的地址不变,堆中存放的是test1.i=12

    六、总结

    本篇主要讲的就是对象的字段如何在内存中是如何赋值的,以及从每一行IL指令分析stfld 的执行过程。从底层分析对象的字段的赋值,可以更加清晰地看到赋值的过程。

    下篇我会从.net底层剖析参数的传递,有兴趣的可以关注我哦!

  • 相关阅读:
    set RowCount 与 top n
    Ubuntu 12.04 64bit 安装编译GCC 4.1.2 绝对原创
    C语言第11课
    Cocos2d-x之MenuItem
    wamp 已安装cakephp Fatal error: You must enable the intl extension to use CakePHP. in XXX
    jQuery性能优化38建议---最引人注目的用户体验!
    在面对变化,撇开NO
    批学习
    JAVA修饰符类型(public,protected,private,friendly)
    【Espruino】NO.15 nRF24L01+无线收发器
  • 原文地址:https://www.cnblogs.com/jackson0714/p/4995948.html
Copyright © 2020-2023  润新知