65.9K
CodeProject 正在变化。 阅读更多。
Home

MSIL 中的曼德勃罗集

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (5投票s)

2001年10月4日

BSD

1分钟阅读

viewsIcon

139020

downloadIcon

574

演示了从 CIL 使用 Windows Forms 和 GDI+

引言

要真正能够编程 .NET,一个优秀的程序员会经常使用 ILDASM,MSIL 反汇编器。这需要至少具备阅读 MSIL 的能力。不幸的是,学习阅读 MSIL 的最佳方法是花一些时间编写它!因此,我开始思考我可以编写什么,它不会太大,但会涵盖足够多的概念,使我能够阅读 MSIL。

我记得大学里的一位朋友,当他学习一门新语言时,总是将生成曼德勃罗集作为他的第一段代码(用 Postscript 编写的曼德勃罗集很有趣)。这似乎可行,所以我选择用 MSIL 编写一个曼德勃罗集生成器。

该代码使用 Windows Forms 显示一个新窗口,然后将像素绘制到该图形表面。

编译

只需使用 ilasm /exe mandelbrot.il 编译代码即可。请记住将 ilasm 添加到您的路径中——.NET Framework SDK 的 bin 文件夹中的 corvars.bat 批处理文件会为您添加它。

这应该会在同一文件夹中生成 mandelbrot.exe

Screenshot of Mandelbrot.il

代码

该代码继承自 System.Windows.Form 并管理自己的绘制。

.class public auto ansi MandelBrotIL extends [System.Windows.Forms]System.Windows.Forms.Form {

该类重写了 System.Windows.Forms.Form (它继承自) 的 OnPaint() 方法。OnPaint 只是设置用于绘制的图形,然后调用 DrawMandelbrot() 来执行实际的绘制

.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
}

DrawMandelbrot() 只是实现了一个基本的曼德勃罗集算法,其细节可以在互联网上的许多地方找到。

.method private hidebysig instance 
           void DrawMandelbrot(class [System.Drawing]System.Drawing.Graphics g,
                               float32 fpMandelWidth, int32 ipIterations) cil managed {

    .locals (
    [0] float32 x, // Complex Real portion
    [1] float32 y, // Complex Imaginary portion
    [2] float32 fpGranularity, // Resolution of image on screen
    [3] int32 ipPixelX, // X position on screen
    [4] int32 ipPixelY, // Y position on screen
    // Escape Velocity locals
    [5] float32 fpX,
    [6] float32 fpY,
    [7] float32 fpXTemp,
    [8] float32 fpYTemp,
    [9] float32 fpX2, // X Squared
    [10] float32 fpY2, // Y Squared
    [11] int32 i // Loop variable used to calc escape velocity
    )
    // Calculate Granularity
    ldc.r4 4
    ldarg fpMandelWidth
    div
    stloc fpGranularity

    // Initialise point on screen
    ldc.i4.0
    dup
    stloc ipPixelX
    stloc ipPixelY

    // Start the real portion off
    ldc.r4 -2.5
    stloc x

NextReal:

    // Start the imaginary portion off
    ldc.r4 -1.5
    stloc y

NextImaginary:

    // Calculate Escape Velocity

    // Initialise locals
    ldloc x
    stloc fpX

    ldloc y
    stloc fpY

    ldloc x
    dup
    mul
    stloc fpX2

    ldloc y
    dup
    mul
    stloc fpY2


    // Initialise i
    ldc.i4.0
    stloc i
NextIteration:

    ldloc x
    ldloc fpX2
    ldloc fpY2
    sub
    add
    stloc fpXTemp

    ldloc y
    ldloc fpY
    ldloc fpX
    ldc.r4 2
    mul
    mul
    add
    stloc fpYTemp

    // Calculate X squared
    ldloc fpXTemp
    dup
    mul
    stloc fpX2

    // Calculate Y squared
    ldloc fpYTemp
    dup
    mul
    stloc fpY2

    // If X Squared plus Y Squared is greater than 4, then we are guaranteed 
    // divergence to Infinity
    ldloc fpX2
    ldloc fpY2
    add
    ldc.r4 4
    bge Divergence

    // The previous values in the sequence become the current values in the sequence
    ldloc fpXTemp
    stloc fpX
    ldloc fpYTemp
    stloc fpY

    // Incrememt i
    ldc.i4.1
    ldloc i
    add
    stloc i

    ldloc i
    ldarg ipIterations
    blt NextIteration // Assume convergence to zero if we reach our iteration limit

Divergence:

    // Draw Pixel. i is now the escape velocity

    // Load the Graphics context
    ldarg g

    // Calculate the color based on the escape velocity

    ldarg ipIterations
    ldloc i
    sub
    stloc i

    // Red
    ldloc i
    ldc.i4 12
    mul
    ldc.i4 256
    rem

    // Green
    ldloc i
    ldc.i4 16
    mul
    ldc.i4 256
    rem

    // Blue
    ldloc i
    ldc.i4 5
    mul
    ldc.i4 256
    rem

    call value class [System.Drawing]System.Drawing.Color 
                           [System.Drawing]System.Drawing.Color::FromArgb(int32,
                                                                          int32,
                                                                          int32)

    // Create a new Pen on the stack
    ldc.r4 1
    newobj instance void [System.Drawing]System.Drawing.Pen::.ctor(value class 
                                              [System.Drawing]System.Drawing.Color,
                                                float32)

    // Load the coords of the point to draw
    ldloc ipPixelX
    ldloc ipPixelY

    // Width and Height
    ldc.i4.2
    dup

    call instance void [System.Drawing]System.Drawing.Graphics::DrawRectangle(class 
                                               [System.Drawing]System.Drawing.Pen,
                                                int32,
                                                int32,
                                                int32,
                                                int32)

    // Next PixelY
    ldc.i4.1
    ldloc ipPixelY
    add
    stloc ipPixelY

    // Advance through the imaginary portion
    ldloc y
    ldloc fpGranularity
    add
    stloc y

    ldloc y
    ldc.r4 1.5
    blt NextImaginary

    // Advance through ipPixelX
    ldc.i4.1
    ldloc ipPixelX
    add
    stloc ipPixelX

    // Start at the top of the screen for the next column
    ldc.i4.0
    stloc ipPixelY

    // Advance through the real portion
    ldloc x
    ldloc fpGranularity
    add
    stloc x

    ldloc x
    ldc.r4 1.5
    blt NextReal

    ret
} // method

历史

  • 2002年6月24日:初始版本
© . All rights reserved.