CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
Note Recall that CIL is not directly executed, but compiled on demand. During the compilation of CIL code,
many of these implementation redundancies are optimized away. Furthermore, if you enable the code optimization
option for your current project (using the Build tab of the Visual Studio Project Properties window), the compiler will
also remove various CIL redundancies.
To understand how CIL leverages a stack-based processing model, consider a simple C# method,
PrintMessage(), which takes no arguments and returns void. Within the implementation of this method,
you will simply print out the value of a local string variable to the standard output stream, like so:
public void PrintMessage()
{
string myMessage = "Hello.";
Console.WriteLine(myMessage);
}
If you were to examine how the C# compiler translates this method in terms of CIL, you would first
find that the PrintMessage() method defines a storage slot for a local variable using the .locals
directive. The local string is then loaded and stored in this local variable using the ldstr (load string) and
stloc.0 opcodes (which can be read as “store the current value in a local variable at storage slot zero”).
The value (again, at index 0) is then loaded into memory using the ldloc.0 (“load the local argument
at index 0”) opcode for use by the System.Console.WriteLine() method invocation (specified using the
call opcode). Finally, the function returns via the ret opcode. Here is the (annotated) CIL code for the
PrintMessage() method (note that I’ve removed the nop opcodes from this listing, for brevity):
.method public hidebysig instance void PrintMessage() cil managed
{
.maxstack 1
// Define a local string variable (at index 0).
.locals init ([0] string myMessage)
// Load a string onto the stack with the value "Hello."
ldstr " Hello."
// Store string value on the stack in the local variable.
stloc.0
// Load the value at index 0.
ldloc.0
// Call method with current value.
call void [mscorlib]System.Console::WriteLine(string)
ret
}
655