今天我开始了 IL 汇编语言的学习,下面都是对一篇文章学习过程的翻译和摘要。
原文:http://www.codeproject.com/dotnet/ilassembly.asp
先从一个 HelloWorld 例子开始:
//
Test.IL
//
A simple programme which prints a string on the console
.assembly
extern
mscorlib {}
.assembly Test
{
.ver
1
:
0
:
1
:
0
}
.module test.exe
.method
static
void
main() cil managed
//
"cil managed" 让编译器编译为托管代码
{
.maxstack
1
//
要加载到 evaluation stack 中的条目数
.entrypoint
ldstr
"
I am from the IL Assembly Language
"
//
加载字符串到 evaluation stack
call
void
[mscorlib]System.Console::WriteLine (
string
)
//
使用上一个语句加载到 evaluation stack 里的那个 string.
ret
}
Evaluation Stack:评估堆栈
a. 该堆栈用于在方法执行之前,存储所需变量的值。
b. 方法执行后,会自动被清空,或存储一个结果。
c. 通过 .maxstack n 的语句可以指定其最大容量(item 数)
例子:简单的加法
//
Add Two Numbers
.assembly
extern
mscorlib {}
.assembly Add
{
.ver
1
:
0
:
1
:
0
}
.module add.exe
.method
static
void
main() cil managed
{
.maxstack
2
.entrypoint
ldstr
"
The sum of 50 and 30 is =
"
call
void
[mscorlib]System.Console::Write (
string
)
ldc.i4.s
50
//
加载单字节的整数
ldc.i4
30
//
加载4个字节的整数
add
call
void
[mscorlib]System.Console::Write (int32)
ret
}
类型列表(注意其中的类型是否为 CLS 兼容的):
IL Name |
.NET Base Type |
Meaning |
CLS Compliant |
Void
|
|
no data, only used as return type |
No |
Bool
|
System.Boolean
|
Boolean Value |
No |
Char
|
System.Char
|
Character Value (16 bit unicode) |
No |
int8
|
System.SByte
|
Single Byte Integer (signed) |
No |
int16
|
System.Int16
|
Two Byte Integer(signed) |
No |
int32
|
System.Int32
|
Four Byte Integer(signed) |
Yes |
int64
|
System.64
|
8 Byte Integer(signed) |
Yes |
native int
|
System.IntPtr
|
Signed Integer |
Yes |
unsigned int8
|
System.Byte
|
One byte integer (unsigned) |
No |
unsigned int16
|
System.UInt16
|
Two byte integer (unsigned) |
No |
unsigned int32
|
System.UInt32
|
Four byte integer (unsigned) |
No
|
unsigned int64
|
System.UInt64
|
Eight byte integer (unsigned) |
Yes |
native unsigned int
|
System.UIntPtr
|
Unsigned Integer |
Yes |
Float32
|
System.Single
|
Four byte Floating Point |
No |
Float64
|
System.Double
|
Eight byte Floating Point |
No |
object
|
System.Object
|
Object type value |
Yes |
&
|
|
Managed Pointer |
Yes |
*
|
System.IntPtr
|
Unmanaged Pointer |
Yes |
typedef
|
System.Typed Reference
|
Special type that holds data and explicitly indicates the type of data. |
Yes |
Array
|
System.Array
|
Array |
Yes |
string
|
System.String
|
String type |
Yes |
除此之外还有一些类型助记符:.i4, .i4.s, .u4 等。
例如如下代码:
call int32 SomeFunction (
string
, int32, float64
<
code lang
=
msil
>
)
其参数分别是相当于 C# 的 string, int, double. 返回一个 int.
这个例子中用到的都是一些 CLS 兼容的类型。如果是自定义的类型呢?看下面的例子:
//
In C#
ColorTranslator.FromHtml(htmlColor)
//
In ILAsm
call instance
string
[System.Drawing]
System.Drawing.ColorTranslator::ToHtml(valuetype
[System.Drawing]System.Drawing.Color)
注意这里的
valuetype 关键字用于指示一个不是基础数据类型的类型。
如何声明变量:
可以用 .locals 指令。
例子及解析:
.locals init (int32,
string
)
//
声明两个变量,一个 int 一个 string.
ldc.i4
34
//
加载整数 34 到 Evaluation Stack
stloc.
0
//
保存到变量 0(变量从 0 开始按索引存取,这里就是上面分配的整形变量)
ldstr
"
Some Text for Local Variable
"
//
加载字符串
stloc.
1
//
赋值给 string 变量(在位置1)
ldloc.
0
//
加载变量 0(整数)的值到 Evaluation Stack.
call
void
[mscorlib]System.Console::WriteLine(int32)
//
打印整数
ldloc.
1
//
加载变量 1(字符串)的值到 Evaluation Stack.
call
void
[mscorlib]System.Console::WriteLine(
string
)
//
打印字符串
以上没有指定变量名称,如果要指定也是可以的:
.locals init (int32 x, int32 y)
要加载这种变量,可以用 stloc x 和 stloc y 语句。
(
To be continued)