C Sharp

"Hello, World" in MSIL

In the Start menu's Run dialog box, type ildasm and click OK. You'll see a nondescript application with a few menu options. At this point, from the File menu, click Open. When the File Open dialog box appears, browse to the folder containing the HelloWorld.exe application you created earlier (on Chapter 3) and select it. As shown in Figure 3-4, things start to look a bit more promising.


Figure 3-4 ILDASM lets you spelunk in the caverns of the manifest and the IL opcodes that make up your .NET application.-

Notice the tree view that ILDASM uses to list the contents of a managed binary. Figure 3-5 shows the various icons used in the ILDASM tree view to describe the parts of a .NET application. As you can see by cross-referencing the icons shown in Figure 3-5 and the "Hello, World" program in ILDASM, HelloWorld.exe consists of a manifest, one class (HelloWorld), two methods (a class constructor and the static method Main), and a bit of class information.


Figure 3-5 The different icons used to denote the parts of a .NET application in ILDASM.-

The most interesting part of "Hello, World" is in the Main method. Double-click the Main method in the ILDASM tree view, and ILDASM will present a window displaying the MSIL for the Main method, as shown in Figure 3-6.


Figure 3-6 To look at the generated MSIL for a method, open the binary in ILDASM and double-click the method.-

"Hello, World," even in MSIL, isn't too exciting, but you can learn a few facts about the generated MSIL to carry over to any .NET application. Let's look at this method line by line to see what I mean.

.method public hidebysig static void Main() il managed
    // Code size    11 (0xb)
    .maxstack 8
    IL_0000:         ldstr     "Hello, World"
    IL_0005:    call void [mscorlib]System.Console::WriteLine
                         (class System.String)
} // end of method HelloWorld::Main

The first line defines the Main method by using the .method MSIL keyword. We can also see that the method is defined as being public and static, which are the default modifiers for the Main method. In addition, however, we see that this method is defined as managed. This is an important distinction because you can also write "unmanaged," or "unsafe," code in C#. Chapter 17, "Interoperating with Unmanaged Code," discusses unmanaged C# code.

The next line of code uses the MSIL .entrypoint keyword to designate this particular method as the entry point to the application. When the .NET runtime executes this application, this is where control will be passed to the program.

The next items of interest are the actual MSIL opcodes on lines IL_0000 and IL0005. The first uses the ldstr (Load String) opcodeto load a hard-coded literal ("Hello, World") onto the stack. The next line of code calls the System.Console.WriteLine method. Notice that the MSIL prefixes the method name with the name of the assembly that defines the method. What's nice about this level of detail in the MSIL is that it means you can more easily write tools like dependency walkers that can look through an application to determine what files are needed for it to execute properly. Additionally, you can see the number of arguments (and their types) that are expected by the method. In this case, the System.Console.WriteLine method will expect a System.String object to be on the stack when it's called. Finally, line IL000a is a simple ret MSIL opcode to return from the method.

ILDASM is a powerful tool. When I refer to the C# compiler's generated MSIL, you can fire up ILDASM and follow along.

To tell whether an EXE or DLL is managed, attempt to open it with ILDASM. If the file is a valid managed file containing MSIL and a manifest, it will be opened. If it's not, you'll receive an error message stating that <your file> has no valid CLR header and cannot be disassembled.