Hello World in IL

I am always fascinated by the inside the hood views of things, how they work, how they all fit in together. Since I program in C# majority of the time, naturally I am interested in learning about how a program written in C# is converted to IL, how the IL code looks for a specific C# program and how the IL is converted to native code. The first step for all this would be to learn IL. I have made several attempts in the past to learn IL but I never made a good effort towards achieving that goal. Today I decided I would write a program IL, and I sure did write one. In keeping with the tradition it is a program that prints the string “Hello, World !” to the console. Here is the C# version:

using System;
namespace HelloWorldIL
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World !");
        }
    }
}

Here is the IL version.

.assembly extern mscorlib {}
.assembly HelloWorldIL {}
.namespace HelloWorldIL
{
    .class Program
    {
        .method static public void Main() cil managed
        {
            .entrypoint
            .maxstack 8
            ldstr "Hello, World !"
            call void [mscorlib] System.Console::WriteLine(string)
            ret
        }
    }
}

I would like to claim that I wrote it without any help, but for the sake of honesty I should say that I peeked at the disassembled code using ILDASM. As you can see the disassembled code is a mess and not so easy to understand, I spent hours cleaning up the code and trying to understand what everything means and the result is helloworldil.il.

The elements that start with a ‘.’ are called directives.

The program starts with a .assembly extern directive. The .assembly extern is used to reference an external assembly. Since mscrolib.dll is the most important assembly for a .NET program, ILASM will automatically add an external reference to it, so from an IL coder’s perspective it is optional to add a .assembly extern directive for mscorlib.dll. The .assembly extern directive has the following syntax:

.assembly extern name  as alias { /* additional directives here */}

The aliasing is optional and is used in the situations where multiple assemblies have same name.

After the .assembly extern directive, we have a .assembly directive. The .assembly directive is used to specify metadata for the assembly which will be generated by ILASM. The .assembly directive has the following syntax:

.assembly name { /* additional directives here */}

For both .assembly and .assembly extern directives we can use additional directives to specify additional attributes for the assembly such as .publickey, .hash, .ver etc. For eg:

The .namespace directive creates a new namespace and the .class directive creates a new type.

Inside the .class directive we put other directives such as .method, .property, .field etc.

The .method directive specifies a method and the cil and managed attributes means that the method contains IL code and that the implementation is managed.

The .entrypoint directive marks the method as the starting point of the application. This means that in IL you can name your entry point method any legal name unlike in C# where it should always be named Main.

The .maxstack sets the size of the evaluation stack and the default value is 8 slots. It limits the number of items permitted simulataneously on the evaluation stack.

The ldstr command loads a string to the evaluation stack.

The call command calls a specified method whose parameters are on the evaluation stack.

The ret command is equivalent to return in C# and returns control to the caller.

I have used the following books to learn more about IL and I think it would be useful for anybody who wants to know more about the inner workings of IL and .NET.

One great tool for learning the underpinnings of .NET is Reflector.

3 thoughts on “Hello World in IL

  1. Great research…………..Hats off to you…………

    I am learning C# ,I had a thought of how could entrypoint in c# deals with two Main() functions i.e with argument and without argument…….

    this code helps a lot in understanding internal functioning……..
    thank you

  2. hi!!! i wanted to make a console application without using Static in main().it can be possible or not…….plssss explain

  3. @Tripti, thanks for your kind words.

    @Rahul, why would you want to have a Main() without using static ? Is there any special reason or is it just to satisfy your curiosity ?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>