---+ Anakrino .NET to C# Decompiler Tests
[[http://www.saurik.com/net/exemplar/][Anakrino]] is a .NET to C# decompiler,
released under a BSD-like license. These tests refer to "Interim #9" (Anakrino9.zip).
Anakrino does not save an entire file of code to write to a source file; I had to
add the text in *bold* to the given output.
The distributed binaries require Windows XP (or perhaps another Windows based .NET JIT).
It would not run under Mono version 0.20 (current in early March 2003).
%TOC%
---++ Fibo
For source, see DecompilerFiboDotNetSource. Decompiled source from Anakrino:
using System;
class Fibo {
private static int fib(int x) {
if (x > 1)
return Fibo.fib(x - 1) + Fibo.fib(x - 2);
return x;
}
public static int Main(string[] args) {
int local0;
int local1;
Exception local2;
int local3;
local1 = 0;
try {
local1 = Convert.ToInt32(args[0]);
}
catch (Exception local2) {
Console.WriteLine("Input error");
local3 = 1;
<{ class ILEngineer::Ops::MSIL::Leave }>
}
local0 = Fibo.fib(local1);
Console.WriteLine("fibonacci({0}) = {1}", local1, local0);
return 0;
return local3;
}
}
There are several errors in this output. Most obviously, there is the _Leave_ code
which should be =return local3=.
The =return local3;= at the end should be removed.
Finally, =local2= is declared twice.
When all these changes are made, the result compiles and runs correctly.
---++ Casting
For source, see DecompilerCastingDotNetSource. Here is the output from Anakrino:
using System;
class Casting {
public static void Main(string[] args) {
char local0;
char local1;
local0 = '';
while (local0 < 128) {
Console.WriteLine("ascii {0} character {1}", local0, local0);
local1 = local0 + 1;
local0 = local1;
}
}
}
The main cast is missing in the =WriteLine= statement.
The character constant for character 0 is ='\0'= , not =''= as given.
The line =local1 = local0 + 1;= needs to be replaced with =local1 = (char) (((int)local0)+1);=.
When all these changes are made, the program compiles
and is correct.
---++ Inner Classes
For source, see DecompilerInnerClassesDotNetSource. When decompiled with Anakrino, the result appears
correct, but tedious to piece together from the individual functions (and constructors).
The =print_names= function decompiles as follows:
public void print_names() {
Console.WriteLine(this.name);
}
The =this.= is not needed.
---++ Sable Test Program
For source, see DecompilerSableDotNetSource.
The decompiler exited with a runtime fault when this program was loaded.
---++ Simple Control Flow
For source, see DecompilerControlFlowDotNetSource.
The decompiler exited with a runtime fault when this program was loaded.
---++ Image Viewer
For source, see DecompilerImageViewerDotNetSource.
This program was compiled with a Microsoft compiler, and so should be easy to decompile.
Unfortunately, it had problems with the same method that caused problems for Salamander:
private static Pixbuf GetPixbufFromFile(string filename) {
Pixbuf local0;
GException local1;
Pixbuf local2;
try {
local0 = new Pixbuf(filename);
local2 = local0;
<{ class ILEngineer::Ops::MSIL::Leave }>;
}
catch (GException local1) {
Console.WriteLine(local1.GetType());
Console.WriteLine("Cannot Open file.");
Environment.Exit(1);
local2 = null;
<{ class ILEngineer::Ops::MSIL::Leave }>;
}
return local2;
}
Also, =local1= is declared twice.
For completeness, here is the =main= function.
public static void Main(string[] args) {
string local0;
ScrolledWindow local1;
VBox local2;
VBox local3;
MenuBar local4;
Menu local5;
MenuItem local6;
MenuItem local7;
MenuItem local8;
Toolbar local9;
Pixbuf local10;
if (args.Length > 0 == 0) {
Console.WriteLine("\nUSAGE: ImageViewer.exe \n");
return;
}
local0 = args[0];
Application.Init();
ImageViewer.window = new Window("File Viewer");
ImageViewer.window.SetDefaultSize(200, 200);
ImageViewer.window.add_DeleteEvent(new EventHandler(null,
ImageViewer.Window_Delete));
local1 = new ScrolledWindow(new Adjustment(IntPtr.Zero),
new Adjustment(IntPtr.Zero));
local2 = new VBox(0, 2);
local3 = new VBox(0, 0);
local4 = new MenuBar();
local5 = new Menu();
local6 = new ImageMenuItem("gtk-close", new AccelGroup(IntPtr.Zero));
local7 = new ImageMenuItem("gtk-open", new AccelGroup(IntPtr.Zero));
local6.add_Activated(new EventHandler(null, ImageViewer.Window_Delete));
local7.add_Activated(new EventHandler(null, ImageViewer.Window_Open));
local5.Append(local7);
local5.Append(new SeparatorMenuItem());
local5.Append(local6);
local8 = new MenuItem("_File");
local8.Submenu = local5;
local4.Append(local8);
local3.PackStart(local4, false, false, 0);
local9 = new Toolbar();
local9.InsertStock("gtk-open", "Open", String.Empty,
new SignalFunc(null, ImageViewer.Window_Open), IntPtr.Zero, 0);
local9.InsertStock("gtk-close", "Close", String.Empty,
new SignalFunc(null, ImageViewer.Window_Delete), IntPtr.Zero, 1);
local3.PackStart(local9, false, false, 0);
local2.PackStart(local3, false, false, 0);
local10 = ImageViewer.GetPixbufFromFile(local0);
ImageViewer.image = new Image(local10);
ImageViewer.Refresh(local0, local10);
local1.AddWithViewport(ImageViewer.image);
local2.PackStart(local1, true, true, 0);
local1.SetPolicy(1, 1);
ImageViewer.window.Add(local2);
ImageViewer.window.ShowAll();
Application.Run();
}
The translation "if (args.Length > 0 == 0)" seems clumsy and confusing.
---++ Conclusion
As of early March 2003, Anakrino is not a mature decompiler.
It may be useful for examining snippets of code here and there,
or even for decompiling small assemblies if you have a fair bit of time spare.
-- Main.MikeVanEmmerik - 07 Mar 2003
CategoryDecompilation