Interface
     The API for MBEL is very simple and straightforward. Everything begins by opening a java.io.InputStream to the input module. This allows the data to come from a wide range of different sources. Once the stream has been opened, it can be used to create an instance of ClassParser, which will begin parsing the module metadata. Once the ClassParser has been constructed, the parseModule() method will return a Module object which is the MBEL representation of the input module. Module is the top-level class in the MBEL library. Every part of the module's metadata is accessible through the Module object. Specifically, the Module contains a vector of TypeDef objects, which represent the definitions of all the classes, interfaces, and ValueTypes within the module. Each TypeDef will have Fields, Methods, Properties, Events, etc, all of which are mutable by the user.
     Once the desired manipulations have been made, the user must then re-emit the module to a file. This is done by creating an Emitter object around the Module you have been manipulating. A Module object contains all the information necessary to recreate a valid EXE/DLL. Once you have created the Emitter, simply call emitModule(java.io.OutputStream) and the file will be written back to the given stream.

Here is an example of how a typical program will use MBEL:
import edu.arizona.cs.mbel.parse.MSILParseException;
import edu.arizona.cs.mbel.emit.Emitter;
import edu.arizona.cs.mbel.mbel.*;
import java.io.*;

Module module=null;
try{
   FileInputStream fin = new FileInputStream("MyModule.exe");
   ClassParser parser = new ClassParser(fin);
   module = parser.parseModule();
}catch(IOException ioe){}
}catch(MSILParseException mpe){}

//
// program performs desired manipulations on the Module
//

try{
   FileOutputStream fout = new FileOutputStream("MyModule.exe");
   Emitter emitter = new Emitter(module);
   emitter.emitModule(fout);
}catch(IOException ioe){}

Example: Creating a Method
One of the primary uses of MBEL is to create and/or edit methods. Consider the following excerpt from a C# program:
public int factorial(int n)
{
   if (n<=0)
      return 1;
   return n*factorial(n-1);
}
The following sample code will create this method using only MBEL API calls, and then add the constructed method to a user-supplied class: (download the source code here)
import edu.arizona.cs.mbel.mbel.*;
import edu.arizona.cs.mbel.instructions.*;
import edu.arizona.cs.mbel.signature.*;

public class example1{
   public void makeFactorial(TypeDef def){
      MethodSignature sig=null;
      LocalVarList locals=null;
      try{
         ParameterSignature nParam = new ParameterSignature(TypeSignature.I4, false);
         nParam.setParameterInfo(new ParameterInfo("n", 0));
         sig = new MethodSignature(
            new ReturnTypeSignature(TypeSignature.I4, false),
            new ParameterSignature[]{nParam}
         );

         locals = new LocalVarList(
            new LocalVar[]{
               new LocalVar(false, TypeSignature.I4)
            }
         );
      }catch(SignatureException se){}

      Method factorial = new Method("factorial", Method.IL,
                                    Method.Public|Method.HideBySig,
                                    sig);

      MethodBody body = new MethodBody(false, 10, locals);
      factorial.setMethodBody(body);

      InstructionList ilist = body.getInstructionList();
      ilist.append(new LDARG(LDARG.LDARG_1));
      ilist.append(new LDC(LDC.LDC_I4_0));

      InstructionHandle target1 = new InstructionHandle(
                                     new LDARG(LDARG.LDARG_1)
                                  );
      ilist.append(new BGT(true, false, target1));

      ilist.append(new LDC(LDC.LDC_I4_1));
      ilist.append(new STLOC(STLOC.STLOC_0));

      InstructionHandle target2 = new InstructionHandle(
                                     new LDLOC(LDLOC.LDLOC_0)
                                  );
      ilist.append(new BR(true, target2));
      ilist.append(target1);
      ilist.append(new LDARG(LDARG.LDARG_0));
      ilist.append(new LDARG(LDARG.LDARG_1));
      ilist.append(new LDC(LDC.LDC_I4_1));
      ilist.append(new SUB());
      ilist.append(new CALL(factorial));
      ilist.append(new MUL());
      ilist.append(new STLOC(STLOC.STLOC_0));
      ilist.append(new BR(true, target2));
      ilist.append(target2);
      ilist.append(new RET());

      def.addMethod(factorial);
   }
}
     The example begins by creating the MethodSignature and LocalVarList for the method. The MethodSignature contains all the information about the parameters and calling convention of the method, and the LocalVarList contains all the information about the local variables declared in the method body. The ParameterInfo object is only used on parameters that appear in a method definition signature, not a method callsite signature. It defines the parameter's name and special flags, and it can optionally contain custom attributes. Conceptually, the MethodSignature belongs to the Method, and the LocalVarList belongs to the MethodBody, which belongs to the Method.
     This particular MethodSignature has a ReturnTypeSignature that indicates the return type of the method is TypeSignature.I4, or a 4-byte signed integer. The TypeSignature class has constants for each of the primitive value types (i.e. I4, U2, R8, etc). The false in the ReturnTypeSignature constructor indicates that the return value is not returned by reference.
     The LocalVarList simply consists of an array of LocalVars, and in this example there is only one, of type TypeSignature.I4, where again the false indicates that the local variable is not passed by reference. Most of the classes in the edu.arizona.cs.mbel.signature library potentially throw a SignatureException when they are constructed, to prevent the user from passing invalid arguments. Thus the MethodSignature and LocalVarList must be constructed within a try/catch block.
     Once the MethodSignature has been created, the Method instance can be created. The arguments to this Method constructor are its name ("factorial"), the flag Method.IL which indicates that this is a standard CIL method, the implementation flags Method.Public and Method.HideBySig which give public access and define the method visibility, and its MethodSignature. Note that the parent of this method is not yet set, and is thus null. The parent of this method will be set after the call to def.addMethod(factorial).
Example: Hello World
There's just no escaping it. Might as well get it out of the way. The following example shows how to build the complete Hello World program from scratch using MBEL. The program is approximately equivalent to the following C# code:
using System;
namespace HelloWorldSpace
{
   class HelloWorld
   {
      static void Main()
      {
         Console.WriteLine("Hello World!");
      }
   }
}
Now here's how you would construct the same program using MBEL:
(download the source code here)
import edu.arizona.cs.mbel.parse.*;
import edu.arizona.cs.mbel.signature.*;
import edu.arizona.cs.mbel.instructions.*;
import edu.arizona.cs.mbel.metadata.*;
import edu.arizona.cs.mbel.mbel.*;
import edu.arizona.cs.mbel.emit.*;
import java.io.*;

public class example2{
   public static void main(String args[]) throws Exception{
      /// Create the Module itself, and set its values ///
      Module module = new Module("hello.exe", new byte[16],
                                 PE_Header.PE_SUBSYSTEM_WINDOWS_CUI);
      AssemblyInfo info = new AssemblyInfo(AssemblyInfo.SHA1, 1, 0, 1, 1, 0,
                                           null, "HelloWorld", "");
      module.setAssemblyInfo(info);


      TypeDef HelloWorld = new TypeDef("HelloWorldSpace", "HelloWorld",
                                       TypeDef.NotPublic|TypeDef.BeforeFieldInit);
      HelloWorld.addMethod(Method.makeDefaultConstructor());

      module.addTypeDef(HelloWorld);

      /// Create the System.Console.WriteLine(string) MethodRef ///
      TypeRef System_Console = new AssemblyTypeRef(AssemblyRefInfo.MSCORLIB, "System", "Console");
      MethodSignature callsitesig = new MethodSignature(
                                       false, false, CallingConvention.DEFAULT,
                                       new ReturnTypeSignature(ReturnTypeSignature.ELEMENT_TYPE_VOID),
                                          new ParameterSignature[]{
                                             new ParameterSignature(TypeSignature.STRING, false)
                                          }
                                    );
      MethodRef WriteLine = new MethodRef("WriteLine", System_Console, callsitesig);

      /// Create the Main method, which prints "Hello World!" ///
      MethodSignature MainSig = new MethodSignature(
                                       false, false, CallingConvention.DEFAULT,
                                       new ReturnTypeSignature(ReturnTypeSignature.ELEMENT_TYPE_VOID),
                                       null
                                    );

      Method Main = new Method("Main", 0, (Method.Private|Method.HideBySig|Method.Static), MainSig);
      HelloWorld.addMethod(Main);

      MethodBody body = new MethodBody(true, 1, null);
      Main.setMethodBody(body);

      InstructionList ilist = body.getInstructionList();
      ilist.append(new LDSTR("Hello World!"));
      ilist.append(new CALL(WriteLine));
      ilist.append(new RET());

      module.setEntryPoint(new EntryPoint(Main));

      /// Emit the module to a file (hello.exe) ///
      FileOutputStream fout = new FileOutputStream("hello.exe");
      Emitter emitter = new Emitter(module);
      emitter.emitModule(fout);
      fout.close();
   }
}
     We begin by making a new Module object. The only public constructor of the Module class will create a new module "from scratch", with many fields preset for convenience. This constructor names the module "hello.exe", creates a null Mvid GUID for it, and sets the target platform. The Mvid GUID is a 16-byte global identifier value. This value is chosen arbitrarily, and may safely be set to all 0s. The argument PE_Header.PE_SUBSYSTEM_WINDOWS_CUI informs MBEL that the target platform for this module is the Windows CUI (command prompt).
     Next, since this module will constitute the entire assembly, we must give it an AssemblyInfo object with information about the assembly we are creating. The AssemblyInfo.SHA1 argument tells MBEL that the hash algorithm used by this assembly will be SHA1. The next 4 arguments are the major version, minor version, build number, and revision number of this assembly. After that is a bit vector of flags, of which this assembly has none. Then comes the public key value, which is a byte array in general, but may be set to null. Finally, we set the name of the assembly to be "HelloWorld", and set the culture string to "" (i.e. no culture).
     Now that the module is created, we must make a class to hold the Main method. We construct a new private TypeDef in the namespace "HelloWorldSpace" with the name "HelloWorld". We then add a default do-nothing constructor to it, by necessity. Now we can begin making the Main method. We know that the only instructions in the Main method will be
   ldstr "Hello World"
   call System.Console.WriteLine
   ret
so before we can make the instructions we must make the method reference to System.Console.WriteLine. For this we need to make a MethodRef object, for which we will need a TypeRef that refers to System.Console. We also need a method callsite signature to distinguish which version of Console.WriteLine we are using. After the MethodRef is complete, we construct the method definition signature of Main and use it in Main's method constructor. Note that Main does not have the HASTHIS or EXPLICITTHIS flags set, because it is static. After Main has been constructed, we construct its MethodBody object, specifying that its locals should be initialized (though it has none) and that it needs only 1 stack slot. Now we simply add the instructions to the MethodBody's InstructionList, and the Main method is finished. The final step is to open a stream to the output file "hello.exe" and emit the module out to it.