CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
}
ldstr "Hello CIL code!"
call void [mscorlib]System.Console::WriteLine(string)
nop
call string [mscorlib]System.Console::ReadLine()
pop
ret
Interacting with CIL: Modifying an *.il File
Now that you have a better understanding of how a basic CIL file is composed, let’s complete the roundtripping experiment. The goal here is to update the CIL within the existing *.il file as follows:
•
Add a reference to the System.Windows.Forms.dll assembly.
•
Load a local string within Main().
•
Call the System.Windows.Forms.MessageBox.Show() method using the local string
variable as an argument.
The first step is to add a new .assembly directive (qualified with the extern attribute) that specifies
your assembly requires the System.Windows.Forms.dll assembly. To do so, update the *.il file with the
following logic after the external reference to mscorlib:
.assembly extern System.Windows.Forms
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
.ver 4:0:0:0
}
Be aware that the value assigned to the .ver directive may differ depending on which version of the
.NET platform you have installed on your development machine. Here, you see
that System.Windows.Forms.dll version 4.0.0.0 is used and has the public key token of
B77A5C561934E089. If you open the GAC (see Chapter 14) and locate your version of the
System.Windows.Forms.dll assembly, you can simply copy the correct version and public key token
value.
Next, you need to alter the current implementation of the Main() method. Locate this method
within the *.il file and remove the current implementation code (the .maxstack and .entrypoint
directives should remain intact), like so:
.method private hidebysig static void
{
.entrypoint
.maxstack 8
// ToDo: Write new CIL code!
}
Main(string[] args) cil managed
Again, the goal here is to push a new string onto the stack and call the MessageBox.Show() method
(rather than the Console.WriteLine() method). Recall that when you specify the name of an external
type, you must make use of the type’s fully qualified name (in conjunction with the friendly name of the
assembly). Also notice that in terms of CIL, every method call documents the fully qualified return type.
Keeping these things in mind, update the Main() method as follows:
660