MSIL 教程(一)
PrintString 就是MSIL版的 Hello, World
在代码中用到的MSIL指令如下:
l .entrypoint— 定义程序的入口点(该函数在程序启动的时候由.NET 运行库调用)
l .maxstack— 定义函数代码所用堆栈的最大深度。C#编译器可以对每个函数设置准确的值, 在例子中,我把他设为8。
用到的MSIL命令如下:
- ldstr string—把一个字符串常量装入堆栈。
- call function(parameters)—调用静态函数。函数的参数必须在函数调用前装入堆栈。
- pop— 取出栈顶的值。当我们不需要把值存入变量时使用。
- ret— 从一个函数中返回。
调用静态函数很简单。我们把函数的参数压入堆栈,调用函数,然后从堆栈中读取函数的返回值(如果是非void函数)。Console.WriteLine 就是一个这样的函数。
下面是代码:
.assembly PrintString {}
/*
Console.WriteLine("Hello, World)"
*/
.method static public void main() il managed
{
.entrypoint // 该函数是程序的入口
.maxstack 8
// *****************************************************
// Console.WriteLine("Hello, World)";
// *****************************************************
ldstr "Hello, World" // 把字符串压入堆栈
// 调用静态的System.Console.Writeline函数
// (函数移除栈顶的字符串)
call void [mscorlib]System.Console::WriteLine
(class System.String)
// *****************************************************
ldstr "Press Enter to continue"
call void [mscorlib]System.Console::WriteLine
(class System.String)
// 调用 System.Console.Read 函数
call int32 [mscorlib]System.Console::Read()
// pop 指令移除栈顶元素
// (移除由Read()函数返回的数字
pop
// *****************************************************
ret
}
赋值
该程序给一个变量赋与int值并把它打印到控制台窗口。
命令:
- ldc.i4.n—把一个 32位的常量n装入堆栈
- stloc.n— 把一个从堆栈中返回的值存入第n(n从0到8)个局部变量
- ldloc.n— 把第n个变量装入堆栈
代码:
.assembly XequalN {}
// int x;
// x = 7;
// Console.WriteLine(x);
.method static public void main() il managed
{
.entrypoint
.maxstack 8
.locals init ([0] int32 x) // 分配一个局部变量
// *****************************************************
// x = 7;
// *****************************************************
ldc.i4.7 // 把常量7装入堆栈
stloc.0 // 把堆栈中的值存入第0个变量
// *****************************************************
// Console.WriteLine(x);
// *****************************************************
ldloc.0 // 把第0个变量装入堆栈
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
数据运算
本程序从控制台读取2个数字,对它们进行简单的运算,然后显示结果。
命令:
- add—2个值相加。命令的参数必须在调用前装入堆栈,该函数从堆栈中移除参数并把运算后的结果压入堆栈。
- sub— 2个值相减。
- mul— 2个值相乘。
代码片段:
.assembly Operations {}
/*
// 程序的C#代码:
int x, y, z;
string s;
Console.WriteLine("Enter x:");
s = Console.ReadLine();
x = Int32.Parse(s);
Console.WriteLine("Enter y:");
s = Console.ReadLine();
y = Int32.Parse(s);
z = x + y;
Console.Write("x + y = ");
Console.Write(z);
Console.WriteLine("");
z = x - y;
Console.Write("x - y = ");
Console.Write(z);
Console.WriteLine("");
z = x * y;
Console.Write("x * y = ");
Console.Write(z);
Console.WriteLine("");
*/
.method static public void main() il managed
{
.entrypoint
.maxstack 8
.locals init ([0] int32 x,
[1] int32 y,
[2] int32 z,
[3] string s)
// *****************************************************
// Console.WriteLine("Enter x:");
// *****************************************************
ldstr "Enter x:" // 把字符装入堆栈
call void [mscorlib]System.Console::WriteLine(string)
// *****************************************************
// s = Console.ReadLine();
// *****************************************************
call string [mscorlib]System.Console::ReadLine()
stloc.3 // 把值存入第3个变量
// *****************************************************
// x = Int32.Parse(s);
// *****************************************************
ldloc.3 // 把第3个变量装入堆栈
// 调用 System.Int32::Parse(string)函数
// 把字符串从堆栈中移除并把解析的结果——int值压入堆栈
call int32 [mscorlib]System.Int32::Parse(string)
stloc.0 // 把值存入第0个变量
// *****************************************************
// 和变量y的一些运算
// *****************************************************
ldstr "Enter y:"
// 装入字符串
call void [mscorlib]System.Console::WriteLine(string)
// 调用
call string [mscorlib]System.Console::ReadLine()
// 调用
stloc.3
//把值存入第3个变量
ldloc.3
//把第3个变量装入堆栈
call int32 [mscorlib]System.Int32::Parse(string)
// 调用
stloc.1
//把值存入第1个变量
// *****************************************************
// z = x + y;
// *****************************************************
ldloc.0 //把第0个变量装入堆栈
ldloc.1 //把第1个变量装入堆栈
// 把这2个值从堆栈中移除,把结果压入堆栈
add
stloc.2 //把值存入第2个变量
// *****************************************************
// Console.Write("x + y = ");
// *****************************************************
ldstr "x + y = " // load string onto stack
call void [mscorlib]System.Console::Write(string)
// *****************************************************
// Console.Write(z);
// *****************************************************
ldloc.2 //把第2个变量装入堆栈
call void [mscorlib]System.Console::Write(int32)
// *****************************************************
// Console.WriteLine("");
// *****************************************************
ldstr "" //装入字符串
call void [mscorlib]System.Console::WriteLine(string)
//相减和相乘运算过程与上面相同
ret
}