IL系列文章之三:Array in IL
来源:互联网 发布:人物标签的词语网络语 编辑:程序博客网 时间:2024/06/06 08:48
IL系列文章之三:
Array in IL
正如题目所言,这一节我们研究IL中的array(数组)。我们将看到如何定义一个数组,如何查询数组元数,使用for语句和foreach语句的异同。
先来看看我用C#写的一段程序:
using System;
class array1
{
public static void
{
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
{
.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
- IL系列文章之四:Array in IL (续)
- IL系列文章之五:Property in IL
- IL系列文章之一:Say Hello to IL
- IL系列文章之一:Say Hello to IL
- IL系列文章之一:Say Hello to IL
- IL
- IL系列文章之二:Make Best Use of Our Tools
- IL系列文章之二:Make Best Use of Our Tools
- IL系列文章之二:Make Best Use of Our Tools
- bug in devil lib, /usr/include/IL/il.h
- IL代码底层运行机制之
- IL 汇编学习笔记(三)
- 关于IL
- IL Disassembler
- IL学习
- il语言
- Delphi中的类和对象
- 如何在Delphi中用代码来完成计算字段的创建
- isapi debug
- IL系列文章之一:Say Hello to IL
- IL系列文章之二:Make Best Use of Our Tools
- IL系列文章之三:Array in IL
- IL系列文章之四:Array in IL (续)
- IL系列文章之五:Property in IL
- Understanding .net CLR garbage collection
- Picking a Winner: .NET vs. J2EE
- 将 Java 程序作为 Linux 的 Daemon 进程以及防止程序多次运行
- 在jb6中编译servlet
- 用Oracle的热备份重建数据库
- Oracle数据库文件大挪移