IL系列文章之三:Array in IL

原创 2003年03月02日 12:15:00

IL系列文章之三:

Array in IL<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

         正如题目所言,这一节我们研究IL中的array(数组)。我们将看到如何定义一个数组,如何查询数组元数,使用for语句和foreach语句的异同。

         先来看看我用C#写的一段程序:

 

using System;

class array1

{

         public static void <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Main ()

         {

                   int [] number;

                   number = new int [6];

                   for(int i = 0;  i < 6; i++)

                   {

                            number[i] = i * i;

                   }

                   foreach(int num in number)

                   {

                            Console.WriteLine(num.ToString());

                   }

         }

}

         这段程序相信大家都看得懂吧(如果看不懂的话最好就别往下看了)。在这段程序中我们看到了C#如何定义一个数组,这和我们以前在C/C++使用的方法不太相同。C#使用了如下两句,来定义一个数组:

                   int [] number;

                   number = new int [6];

而在C/C++中使用一句

                   int number[6];

就够了。产生这种差异的缘由何在呢?别慌,马上就能看到。还有一点,C#中有foreach语句,这个语句与传统的for语句比较起来又如何呢?看下面,是上面的程序用ildasm反编译产生的(为了大家能看得更明白,我对反编译产生的il程序做了一些修改)。

 

.assembly array1{}

 

.class private auto ansi beforefieldinit array1

       extends [mscorlib]System.Object

{

  .method public static void  Main() cil managed

  {

    .entrypoint

    .maxstack  4

    .locals init (int32[] V_0,//int[] number

             int32 V_1,//i

             int32 V_2,

             int32[] V_3,//a pointer of array

             int32 V_4)

                   ldc.i4.6//load int32 const 6(length of the array) onto the stack

                   newarr     [mscorlib]System.Int32//number = new int[6],

//length of the array must be loaded onto the stack before

                   stloc.0//number

                   ldc.i4.0//load first local(V_0) onto the stack

                   stloc.1//int i = 0

                   br.s       loopfor      //goto “loopfor”, “loopfor” is only a lable

         //startfor is a lable too

    startfor:  ldloc.0//number

                   ldloc.1//load V_1 onto the stack

                   ldloc.1

                   ldloc.1

                   mul//multiply

                   stelem.i4//i = i * i

                   ldloc.1

                   ldc.i4.1

                   add

                   stloc.1//i = i + 1

    loopfor:  ldloc.1

                   ldc.i4.6

                   blt.s      startfor//if i(V_1) less than 6, goto “startfor”

 

                   ldloc.0

                   stloc.3//look it!!

                   ldc.i4.0

                   stloc.s    V_4

                   br.s       loopforeach

 

    startforeach:  ldloc.3

                   ldloc.s    V_4

                   ldelem.i4

                   stloc.2

                   ldloca.s   V_2//load address of local_2(V_3)

                   call       instance string [mscorlib]System.Int32::ToString()

                            //cast int to a new string instance and stord it into local_2

                   call       void [mscorlib]System.Console::WriteLine(string)//print it

                   ldloc.s    V_4

                   ldc.i4.1

                   add

                   stloc.s    V_4

    loopforeach:  ldloc.s    V_4//index of V_3[]

                   ldloc.3

                   ldlen

                   conv.i4//conver len to int32

                   blt.s      startforeach

 

                   ret//return, must exist, or else the program will stop here

  } // end of method array1::Main

}

         分析这段程序我们可以看出来定义一个数组的三个步骤,不知你看出了没有?

1.   定义一个数组指针,int32[] V_0

2.   将数组长度移到堆栈顶,ldc.i4.6

3.   为其分配空间,newarr [mscorlib]System.Int32

这下明白了C#中的数组为什么要通过两个步骤来定义了吧。其原因就在于在C#中我们是把数组放到托管堆上,而在C++中使用(int number[6])数组不是放在堆上的。IL能做C#不能做到的事情,如数组的下界可以不从0开始等(下次有机会写个例子J)。

为数组元素赋值,需要四个步骤,

1.     将数组指针移到栈顶,ldloc.0

2.     将数组元素的Index移到栈顶,ldloc.1

3.     将要赋的值移到栈顶(这里是同过mul运算实现),

4.     将值从栈顶移出,赋给元素,stelem.i4

选择数组元素的方法和上面差不多,只是用不着第3步了,第4步的st换成ld

对于for语句和foreach语句其实没有本质的差异。使用foreach语句时,IL会预先产生一个数组指针int32[] V_3,在遍历数组时再把已知数组的指针赋给这个指针,以后的指令就和for语句相差无几了。

        关于一维数组的用法基本上差不多了,下一次我可能要写一些关于多维数组和锯齿数组的内容。

        待续……

IL系列文章之四:Array in IL (续)

IL系列文章之四:Array in IL (续)上次谈了Array中的一维数组,这次要谈的是多维数组和锯齿形数组。多维数组其实就是数组的数组(好像不如Array of Array那么好听)。上次说过我...
  • windfast_2000
  • windfast_2000
  • 2003年03月08日 14:56
  • 866

IL文件修改提高篇

IL文件修改提高篇 ================================== Object:    熟悉强名字签名之后的代码处理 =============================...
  • buguyiqie
  • buguyiqie
  • 2009年05月08日 22:45
  • 1969

轻松读懂IL

学习一下IL指令,把有用的东西分享给大家。
  • xiaouncle
  • xiaouncle
  • 2016年10月10日 10:40
  • 1056

【Unity优化】我所理解的IL指令

我所理解的IL指令,这里目前只列举了一些常见指令,box、unbox、newobj、ldc、stloc等等,我认为比较重要的指令,学习Unity最好是要深刻了解C#较为底层的IL实现。...
  • AndrewFan
  • AndrewFan
  • 2017年03月02日 21:39
  • 1773

IL 语法

MSDN相关: 原文:http://www.cnblogs.com/Peter-Zhang/articles/2044794.html .assembly extern mscorlib {   ...
  • Joyhen
  • Joyhen
  • 2015年08月05日 10:28
  • 1481

读懂IL代码就这么简单 (一)

转自 http://www.lupaworld.com/article-229958-1.html 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道...
  • cp790621656
  • cp790621656
  • 2015年06月20日 14:01
  • 1654

IL文件修改入门篇

注:原文地址:http://www.cnblogs.com/midea0978/articles/81071.html================================== Object...
  • maji9370
  • maji9370
  • 2010年06月08日 12:25
  • 3103

OpenMAX IL介绍与其体系

OpenMax IL规范翻译
  • Sailingthink
  • Sailingthink
  • 2014年05月26日 09:42
  • 2435

IL反汇编器(ILDASM)和IL汇编器(ILASM)Hello World小demo

最近在看Enpert .NET 2.0 IL Assembler这本书,可能会花去我很多时间,不过只是看了第一张就被它折服了,原作者简直是庖丁解牛,层层深入。翻译又是那么牛B,此书建议有想深入了解NE...
  • Joyhen
  • Joyhen
  • 2015年08月10日 16:36
  • 2604

浅谈C#中IL

一、前言 IL是什么?  Intermediate Language (IL)微软中间语言 C#代码编译过程? C#源代码通过LC转为IL代码,IL主要包含一些元数据和中间语言指令; JIT...
  • neil3611244
  • neil3611244
  • 2017年05月05日 15:21
  • 157
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IL系列文章之三:Array in IL
举报原因:
原因补充:

(最多只允许输入30个字)