您的位置:首页 > 编程语言

《Inside Microsoft IL Assembler》学习笔记1:初步认识IL代码

2007-07-01 19:35 435 查看
在《Inside Microsoft IL Assembler》一书的开始部分,给出了一段典型的IL代码。代码的功能很简单,从终端接受一个输入,判断这个输入是奇数还是偶数,并在屏幕上返回结果:

1//----------- Program header

2.module OddOrEven.exe

5//----------- Class declaration

6//----------- Global items

.field public static valuetype CharArray8 Format at FormatData

//----------- Data declaration

.data FormatData = bytearray(25 64 00 00 00 00 00 00) //% d . . . . . .

//----------- Value type as placeholder

.class public explicit CharArray8

//----------- Calling unmanaged code

.method public static pinvokeimpl("msvcrt.dll" cdecl)


看了书内的说明,结合自己的理解,我给这一段代码添加了详细的注释,相信对所有IL代码的初学者都会有所帮助,加上注释之后的代码如下:

1//----------- Program header

2.assembly extern mscorlib //说明要引用外部程序集mscorlib.dll(这里只能写文件名,而不能加扩展名)

3.assembly OddOrEven //指明了当前应用(程序集)的名称

6.module OddOrEven.exe //定义了一个模块的元数据,用来指定当前模块

9//----------- Class declaration

.namespace Odd.or //namespace不是一个单独的元数据项,只是它定义范围内的类型的前缀

//----------- Global items

//全局量属于它声明所在的模块(module),它们无法被别的程序集访问。

.field public static valuetype CharArray8 Format at FormatData

//----------- Data declaration

.data FormatData = bytearray(25 64 00 00 00 00 00 00) //定义了模块中一个名为FormatData的数据段,它含有8个字节,其中前两个字节分别为

//%(0x25)和d(0x64),后面6个字节都是0。任何数据都可以用bytearray来表示,比如在前面的程序中,ldstr "odd!"就完全可以用

//ldstr bytearray(6F 00 64 00 64 00 21 00 00 00)来代替

//----------- Value type as placeholder

.class public explicit CharArray8

//在这里我们就用这样一个8字节的值类型作为全局字段Format的类型。

//----------- Calling unmanaged code

.method public static pinvokeimpl("msvcrt.dll" cdecl)

//方法位于非托管程序集msvcrt.dll,其中cdecl是CallingConvention枚举的一个可选值,表明由调用方来清理堆栈,这样才能支持可变参数的调用。

//可以看到,这里声明的并非一个实际的非托管方法,而是由运行时产生的“存根”(stub),这个存根可以由托管代码直接访问。


接下来,为了能让自己的理解更清晰,我又将IL代码反编译成了C#代码如下:

1using System.Runtime.InteropServices;

2namespace Odd.or

3

//下面是一些全局类

[StructLayout(LayoutKind.Explicit, Size=8)]

public struct CharArray8

public static CharArray8 Format; // data size: 8 bytes

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl, PreserveSig=false)]

public static extern unsafe int sscanf(string A_0, sbyte* A_1, __arglist);


本来,我是希望把这段C#代码重新编译为IL,从而检验反编译器的准确性,但我发现这段C#代码编译的时候会出错,我看了出错说明,不清楚应该怎样改动代码才能通过编译。希望有心的朋友看一下这段C#,或者拷贝到本地编译一下,然后帮我指出其中的错误,多谢了!

参考资料:MSIL instruction table
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: