原文:http://www.codeproject.com/dotnet/ilassembly.asp
条件语句
先来看一个简单的跳转:
br 的作用类似于高级语言的 goto 语句,如果你能确定 target 语句在 br 语句的 -128 到 127byte 范围内,则可以用 br.s 代替。因为 br.s 会使用 int8 而不是 int32 保存用于跳转的位移量。
有条件的跳转语句
这里 ble 表示如果堆栈中第一个值小于等于第二个,则跳转。
其他还有一些跳转条件:
beq(==), bne(!=), bge(>=), bgt(>) ble(<=), blt(<)
brfalse(栈顶元素为 0),
brtrue(栈顶元素非 0)
循环
循环也是使用普通的分支语句来跳转,可以用一个 loop index 来判断循环的终止条件。
例子:
用比较直观的方式翻译为 C# 代码,大致上相当于:
(注:这个代码是为了便于和 IL 对照,实际并非最简单的写法)
如何创建方法
看代码:
如何用引用的方式传参:
创建类和名称空间
在 ILAsm 中,类可以有如下的 访问级别修饰符:
对于类的方法和字段,可以有更多的修饰符,详见 MSDN.
( To be continued)
条件语句
先来看一个简单的跳转:
br JumpOver
//
或用 br.s 代替 br
// 这里的其他代码会被跳过。。。
//
JumpOver:
// 这里的代码将被执行
// 这里的其他代码会被跳过。。。
//
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
}
.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
}
{
// 定义两个局部变量
.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 ++ ;
}
}
{
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
}
// 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
}
{
.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
}
}
}
// 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 |
| visible to class, namespace and objects (all) |
|
| visible inside the class only |
|
| visible to class and derived classes only |
|
| visible within same assembly only |
|
| visible within derived classes of the same assembly |
|
| visible to derived classes and those of the same assembly |
|
| as that the private, but it can not be refereneced |
|
对于类的方法和字段,可以有更多的修饰符,详见 MSDN.
( To be continued)