原文:http://www.codeproject.com/dotnet/ilassembly.asp
条件语句
先来看一个简单的跳转:
br JumpOver
//
或用 br.s 代替 br
//
这里的其他代码会被跳过。。。
//
JumpOver:
//
这里的代码将被执行
br 的作用类似于高级语言的 goto 语句,如果你能确定 target 语句在 br 语句的 -128 到 127byte 范围内,则可以用 br.s 代替。因为 br.s 会使用 int8 而不是 int32 保存用于跳转的位移量。
有条件的跳转语句
//
Branching.il
.method
static
void
main() cil managed
{
.maxstack
2
.entrypoint
//
Takes First values from the User
ldstr
"
Enter First Number
"
call
void
[mscorlib]System.Console::WriteLine (
string
)
call
string
[mscorlib]System.Console::ReadLine ()
call int32 [mscorlib]System.Int32::Parse(
string
)
//
Takes Second values from the User
ldstr
"
Enter Second Number
"
call
void
[mscorlib]System.Console::WriteLine (
string
)
call
string
[mscorlib]System.Console::ReadLine ()
call int32 [mscorlib]System.Int32::Parse(
string
)
ble Smaller
ldstr
"
Second Number is smaller than first.
"
call
void
[mscorlib]System.Console::WriteLine (
string
)
br Exit
Smaller:
ldstr
"
First number is smaller than second.
"
call
void
[mscorlib]System.Console::WriteLine (
string
)
Exit:
ret
}
这里 ble 表示如果堆栈中第一个值小于等于第二个,则跳转。
其他还有一些跳转条件:
beq(==), bne(!=), bge(>=), bgt(>) ble(<=), blt(<)
brfalse(栈顶元素为 0),
brtrue(栈顶元素非 0)
循环
循环也是使用普通的分支语句来跳转,可以用一个 loop index 来判断循环的终止条件。
例子:
.method
static
void
main() cil managed
{
//
定义两个局部变量
.locals init (int32, int32)
.maxstack
2
.entrypoint
ldc.i4
4
stloc.
0
//
变量0 = 4,循环的上限,total 5
ldc.i4
0
stloc.
1
//
变量1 = 0,计数器
Start:
//
判断计数器是否超出范围
ldloc.
1
ldloc.
0
bgt Exit
ldloc.
1
call
void
//
打印出计数器的当前值
[mscorlib]System.Console::WriteLine(int32)
//
增加计数器
ldc.i4
1
ldloc.
1
add
stloc.
1
br Start
Exit:
ret
}
用比较直观的方式翻译为 C# 代码,大致上相当于:
(注:这个代码是为了便于和 IL 对照,实际并非最简单的写法)
public
static
void
Main()
{
int
max, counter;
max
=
4
;
counter
=
0
;
while
(
true
)
{
if
(counter
>
max)
break
;
Console.WriteLine(counter);
counter
++
;
}
}
如何创建方法
看代码:
//
Methods.il
//
Creating Methods
.assembly
extern
mscorlib {}
.assembly Methods
{
.ver
1
:
0
:
1
:
0
}
.module Methods.exe
.method
static
void
main() cil managed
{
.maxstack
2
.entrypoint
ldc.i4
10
ldc.i4
20
call int32 DoSum(int32, int32)
call
void
PrintSum(int32)
ret
}
.method
public
static
int32 DoSum (int32 , int32 ) cil managed
{
.maxstack
2
ldarg.
0
ldarg.
1
add
ret
}
.method
public
static
void
PrintSum(int32) cil managed
{
.maxstack
2
ldstr
"
The Result is :
"
call
void
[mscorlib]System.Console::Write(
string
)
ldarg.
0
call
void
[mscorlib]System.Console::Write(int32)
ret
}
如何用引用的方式传参:
.method
static
void
main() cil managed
{
.maxstack
2
.entrypoint
.locals init (int32, int32)
ldc.i4
10
stloc.
0
ldc.i4
20
stloc.
1
ldloca
0
//
加载变量0 的地址到 Evaluation Stack
ldloc.
1
call
void
DoSum(int32
&
, int32 )
ldloc.
0
//
再次加载变量0, 这次是值而不是地址
call
void
[mscorlib]System.Console::WriteLine(int32)
ret
}
.method
public
static
void
DoSum (int32
&
, int32 ) cil managed
{
.maxstack
2
.locals init (int32)
//
加载地址,并把值复制到局部变量
ldarg.
0
ldind.i4
//
读取栈顶的地址,根据这个地址去读取一个 int 值,把值写到堆栈
stloc.
0
//
保存到局部变量
ldloc.
0
//
做加法
ldarg.
1
add
stloc.
0
ldarg.
0
ldloc.
0
stind.i4
//
设定一个内存地址为整形值。op1: 地址,op2: 值
ret
}
创建类和名称空间
//
Classes.il
//
Creating
Classes
.assembly
extern
mscorlib {} .assembly Classes
{ .ver
1
:
0
:
1
:
0
}
.module Classes.exe
.
namespace
HangamaHouse
{
//
ansi 表示该类中每一个字符串都要被转换为 ANSI 字符串。可选的其他值有:unicode, autochar
//
auto 表示运行时会在非托管的内存中,为该类的成员自动选择合适的内存布局(layout). 可选的其他值有:sequential(顺序布局),explicit(严格定义)。详细参考 msdn 里的 StructLayout 或 LayoutKind 枚举
//
//
不指定的情况下,auto 和 ansi 是默认值。
.
class
public
ansi auto Myclass extends [mscorlib]System.Object
{
.method
public
static
void
main() cil managed
{
.maxstack
1
.entrypoint
ldstr
"
Hello World From HangamaHouse.MyClass::main()
"
call
void
[mscorlib]System.Console::WriteLine(
string
)
ret
}
}
}
在 ILAsm 中,类可以有如下的
访问级别修饰符:
ILAsm Name |
Description |
C# Name |
Public
|
visible to class, namespace and objects (all) |
public
|
Private
|
visible inside the class only |
private
|
Family
|
visible to class and derived classes only |
protected
|
assembly
|
visible within same assembly only |
internal
|
familyandassem
|
visible within derived classes of the same assembly |
N/A
|
familyorassem
|
visible to derived classes and those of the same assembly |
protectedinternal
|
privatescope
|
as that the private, but it can not be refereneced |
N/A
|
对于类的方法和字段,可以有更多的修饰符,详见 MSDN.
(
To be continued)