在.NET框架中,MSIL(Microsoft Intermediate Language)是一种中间语言,用于在.NET环境下编译和执行代码。如果经常使用ILDASM(MSIL反编译器),那么至少需要能够阅读MSIL。不幸的是,学习阅读MSIL的最佳方式是花费一些时间来编写它。因此,想到了一个既不太复杂,又能涵盖足够概念的项目,以便能够阅读MSIL。
记得在大学时,一个朋友在学习新语言时,总是首先生成曼德勃罗集作为他的第一段代码(用Postscript编写的曼德勃罗集很有趣)。这似乎可行,所以选择用MSIL编写一个曼德勃罗集生成器。
代码使用Windows Forms来显示一个新窗口,然后在该图形表面上绘制像素。
通过以下命令编译代码:
ilasm /exe mandelbrot.il
请确保将ilasm添加到路径中 -.NETFramework SDK的bin文件夹中的批处理文件corvars.bat会为添加它。
这应该会在同一个文件夹中生成mandelbrot.exe。
代码继承自System.Windows.Forms.Form,并管理自己的绘制。
MSIL代码如下:
.class public auto ansi MandelBrotIL extends [System.Windows.Forms]System.Windows.Forms.Form {
.method family hidebysig virtual instance void OnPaint(class [System.Windows.Forms]System.Windows.Forms.PaintEventArgs e) cil managed {
ldarg.0
ldarg e
call instance class [System.Drawing]System.Drawing.Graphics [System.Windows.Forms]System.Windows.Forms.PaintEventArgs::get_Graphics()
ldc.r4 200 // Width in pixels
ldc.i4 250 // Iterations before we assume convergence to zero
call instance void ThunderMain.Demo.MandelBrotIL::DrawMandelbrot(class [System.Drawing]System.Drawing.Graphics, float32, int32)
ret
}
.method private hidebysig instance void DrawMandelbrot(class [System.Drawing]System.Drawing.Graphics g, float32 fpMandelWidth, int32 ipIterations) cil managed {
// Locals declaration...
// Calculate Granularity
ldc.r4 4
ldarg fpMandelWidth
div
stloc fpGranularity
// Initialize point on screen
ldc.i4.0
dup
stloc ipPixelX
stloc ipPixelY
// Start the real portion off
ldc.r4 -2.5
stloc x
// Start the imaginary portion off
ldc.r4 -1.5
stloc y
// Calculate Escape Velocity...
// Draw Pixel...
// Next PixelY...
// Advance through the imaginary portion...
// Advance through ipPixelX...
// Start at the top of the screen for the next column...
// Advance through the real portion...
ret
}
}
DrawMandelbrot()方法简单地实现了一个基本的曼德勃罗算法,其详细信息可以在互联网上的许多地方找到。
在这个方法中,定义了一组局部变量来存储计算过程中的值。计算了屏幕上图像的分辨率(Granularity),初始化了屏幕上的点(ipPixelX, ipPixelY),并开始了实部(x)和虚部(y)的计算。
接下来,进入一个循环,计算逃逸速度。如果X平方加上Y平方大于4,那么可以确定它将发散到无穷大。否则,继续迭代,直到达到迭代限制,然后假设它收敛到零。
在每次迭代中,更新X和Y的值,并计算X平方和Y平方。如果它们之和大于4,绘制像素,并根据逃逸速度计算颜色。然后,继续绘制下一个像素。