CodeKicks.com
Focus on Microsoft Technologies - Tutorials, Articles, Code Samples.

Tuesday, June 24, 2008

.NET Assemblies Tutorial Part 3 of 5

.NET Assemblies Tutorial Part 1 of 5 - An Overview of .NET Assemblies
.NET Assemblies Tutorial Part 2 of 5 - Single-File and Multifile Assemblies
.NET Assemblies Tutorial Part 3 of 5 - The Role of the Common Intermediate Language
.NET Assemblies Tutorial Part 4 of 5 - The Role of .NET Type Metadata
.NET Assemblies Tutorial Part 5 of 5 - The Role of the Assembly Manifest

The Role of the Common Intermediate Language

Now that you have a better feel for .NET assemblies, let's examine the role of the common intermediate language (CIL) in a bit more detail. CIL is a language that sits above any particular platform-specific instruction set. Regardless of which .NET-aware language you choose, the associated compiler emits CIL instructions. For example, the following Visual Basic 2008 code models a trivial calculator. Don't concern yourself with the exact syntax for now, but do notice the format of the Add() function in the Calc class:

' Calc.vb
Imports System

Namespace CalculatorExample
' Defines the program's entry point.
Module Program
Sub Main()
Dim ans As Integer
Dim c As New Calc()
ans = c.Add(10, 84)

Console.WriteLine("10 + 84 is {0}.", ans)
Console.ReadLine()
End Sub
End Module

' The VB 2008 calculator.
Class Calc
Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer

Return x + y
End Function
End Class
End Namespace


Once the VB 2008 compiler (vbc.exe) compiles this source code file, you end up with a single-file executable assembly that contains a manifest, CIL instructions, and metadata describing each aspect of the Calc and Program types.


If you were to open this assembly using the ildasm.exe utility (examined a little later in this chapter), you would find that the Add() method is represented using CIL such as the following:



.method public instance int32 Add(int32 x, int32 y) cil managed
{
// Code size 9 (0x9)
.maxstack 2
.locals init ([0] int32 Add)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: add.ovf
IL_0004: stloc.0
IL_0005: br.s IL_0007
IL_0007: ldloc.0
IL_0008: ret
} // end of method Calc::Add




Don't worry if you are unable to make heads or tails of the resulting CIL code for this method. In reality, a vast majority of .NET developers could care less about the details of the CIL programming language. Simply understand that the Visual Basic 2008 compiler translates your code statements into terms of CIL.



Now, recall that this is true of all .NET-aware compilers. To illustrate, assume you created this same application using C#, rather than VB 2008 (again, don't sweat the syntax, but do note the similarities in the code bases):



// Calc.cs
using System;

namespace CalculatorExample
{
// Defines the program's entry point.
public class Program
{
static void Main()
{
Calc c = new Calc();
int ans = c.Add(10, 84);
Console.WriteLine("10 + 84 is {0}.", ans);
Console.ReadLine();
}
}

// The C# calculator.
public class Calc
{
public int Add(int x, int y)
{ return x + y; }
}
}


If you examine the CIL for the Add() method, you find similar instructions (slightly tweaked by the C# compiler):



.method public hidebysig instance int32 Add(int32 x, int32 y) cil managed
{
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 CS$1$0000)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // end of method Calc::Add




Benefits of CIL



At this point, you might be wondering exactly what is gained by compiling source code into CIL rather than directly to a specific instruction set. One benefit is language integration. As you have already seen, each .NET-aware compiler produces nearly identical CIL instructions. Therefore, all languages are resolved to a well-defined binary arena that makes use of the same identical type system.



Furthermore, given that CIL is platform-agnostic, the .NET Framework itself is platform-agnostic, providing the same benefits Java developers have grown accustomed to (i.e., a single code base running on numerous operating systems). In fact, .NET distributions already exist for many non-Windows operating systems (more details at the conclusion of this chapter). In contrast to the J2EE platform, however, .NET allows you to build applications using your language of choice.



Compiling CIL to Platform-Specific Instructions



Due to the fact that assemblies contain CIL instructions, rather than platform-specific instructions, CIL code must be compiled on the fly before use. The entity that compiles CIL code into meaningful CPU instructions is termed a just-in-time (JIT) compiler, which sometimes goes by the friendly name of Jitter. The .NET runtime environment leverages a JIT compiler for each CPU targeting the runtime, each optimized for the underlying platform.



For example, if you are building a .NET application that is to be deployed to a handheld device (such as a Pocket PC or .NET-enabled cell phone), the corresponding Jitter is well equipped to run within a low-memory environment. On the other hand, if you are deploying your assembly to a back-end server machine (where memory is seldom an issue), the Jitter will be optimized to function in a high-memory environment. In this way, developers can write a single body of code that can be efficiently JIT-compiled and executed on machines with different architectures.



Furthermore, as a given Jitter compiles CIL instructions into corresponding machine code, it will cache the results in memory in a manner suited to the target operating system. In this way, if a call is made to a method named PrintDocument(), the CIL instructions are compiled into platformspecific instructions on the first invocation and retained in memory for later use. Therefore, the next time PrintDocument() is called, there is no need to recompile the CIL.



.NET Assemblies Tutorial Part 1 of 5 - An Overview of .NET Assemblies


.NET Assemblies Tutorial Part 2 of 5 - Single-File and Multifile Assemblies


.NET Assemblies Tutorial Part 3 of 5 - The Role of the Common Intermediate Language


.NET Assemblies Tutorial Part 4 of 5 - The Role of .NET Type Metadata


.NET Assemblies Tutorial Part 5 of 5 - The Role of the Assembly Manifest


Post a Comment