---+ 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