<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kenny Kerr : Introduction to MSIL</title><link>http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx</link><description>Tags: Introduction to MSIL</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Introduction to MSIL – Part 8 – The for each Statement</title><link>http://weblogs.asp.net/kennykerr/archive/2004/12/15/introduction-to-msil-part-8-the-for-each-statement.aspx</link><pubDate>Wed, 15 Dec 2004 16:26:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:316014</guid><dc:creator>KennyKerr</dc:creator><slash:comments>2</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/12/15/introduction-to-msil-part-8-the-for-each-statement.aspx#comments</comments><description>&lt;p&gt;The &lt;strong&gt;for each&lt;/strong&gt; statement; popularized by &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconUsingForEach.asp"&gt;Visual Basic&lt;/a&gt;, humbly accepted by &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcstdlib/html/vclrfalgorithmforeach.asp"&gt;C++&lt;/a&gt;, and forever immortalized by a &lt;a href="http://www.google.com/search?hl=en&amp;amp;q=Anders+Hejlsberg"&gt;creation&lt;/a&gt; lovingly known as &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrftheforeachstatement.asp"&gt;ECMA-334&lt;/a&gt; (OK so some people simply call it C#). &lt;/p&gt;&lt;p&gt;In this installment of my open-ended series entitled &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;Introduction to MSIL&lt;/a&gt;, I am talking about one of the most popular statements in commercially successful programming languages. Whether your focus has been on Visual Basic, COM, Standard C++, or .NET (or all of the above) you&amp;rsquo;ve inevitably come across some form of the &lt;strong&gt;for each&lt;/strong&gt; statement.&lt;/p&gt;&lt;p&gt;You may have noticed a trend in this series. As we dig deeper into more interesting constructs, the focus is less and less on MSIL instructions and more on language design and compiler implementations. There is really nothing especially new in the instructions you might use to implement a &lt;strong&gt;for each&lt;/strong&gt; statement. Nevertheless it is useful to understand what makes the statement work and how it is interpreted and converted to MSIL instructions depending on the context in which it is used. This is where you thank your lucky stars that your boss lets you write code in a language with statements that abstract away the dirty secrets hidden behind their elegant exteriors. &lt;strong&gt;for each &lt;/strong&gt;is just such a statement.&lt;/p&gt;&lt;p&gt;Variations of the &lt;strong&gt;for each &lt;/strong&gt;statement, as it relates to .NET, can be found in C#, Visual Basic .NET and C++/CLI. There may also be other languages with a similar statement that I&amp;rsquo;m not aware of. The examples in this part of the series use C++/CLI only because C# and VB get enough press as it is. As I&amp;rsquo;ve said before, I am not focusing on a particular compiler&amp;rsquo;s implementation, but rather demonstrating the techniques that may be used by compilers in general.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s start with a simple example:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;array&amp;lt;int&amp;gt;^ numbers = gcnew array&amp;lt;int&amp;gt; { 1, 2, 3 };&lt;br /&gt;&amp;nbsp;&lt;br /&gt;for each (int element in numbers)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console::WriteLine(element);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;numbers is a synthesized reference type extending the built-in System.Array type. It is initialized with three elements and the &lt;strong&gt;for each&lt;/strong&gt; statement executes the statements in the scope block for each of the elements. Pretty straight forward; I&amp;rsquo;m sure you can imagine the equivalent code in your language of choice. Quite predictably this can be implemented in terms of the following set of instructions:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .locals init (int32[] numbers,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 index)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Create the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; newarr int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Populate the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.0 // index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1 // value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stelem.i4&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1 // index &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.2 // value &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stelem.i4&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.2 // index &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.3 // value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stelem.i4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _CONDITION&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_LOOP:&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc index &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;_CONDITION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldlen&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; beq _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// for each statements&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldelem.i4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(int32)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _LOOP&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The only instructions not already discussed in this series are those related to arrays. The &lt;strong&gt;newarr&lt;/strong&gt; instruction pops an integer off the stack indicating the number of elements in the array. It then creates the array of the given type and pushes a reference to it onto the stack. The &lt;strong&gt;stelem&lt;/strong&gt; instruction replaces an element in an array with a given value. The stack needs to be prepopulated with a reference to the array, the index of the element in the array, and the value to store at the given position. Finally, the &lt;strong&gt;ldelem&lt;/strong&gt; instruction loads an element from an array and pushes it onto the stack by first popping off a reference to an array as well as the index into the array.&lt;/p&gt;&lt;p&gt;As you can see, this is not unlike the code that might be generated for a &lt;strong&gt;for&lt;/strong&gt; statement looping over the same elements, as discussed in &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/23/233471.aspx"&gt;part 6&lt;/a&gt;. Of course the &lt;strong&gt;for each&lt;/strong&gt; statement can be used with more than just types deriving from System.Array. In fact it is capable of enumerating the elements of any type that either implements the IEnumerable interface or even a type providing the same functionality without actually implementing that interface. The degree of support naturally depends on the scope of your language specific implementation. Some languages could even, nay, do provide support for completely unrelated containers in the for each statement. Consider the following example using the Standard C++ Library vector container class:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;std::vector&amp;lt;int&amp;gt; numbers;&lt;br /&gt;numbers.reserve(3);&lt;br /&gt;numbers.push_back(1);&lt;br /&gt;numbers.push_back(2);&lt;br /&gt;numbers.push_back(3);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;for each (int element in numbers)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; std::cout &amp;lt;&amp;lt; element &amp;lt;&amp;lt; std::endl;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;In this example, the compiler calls the vector&amp;rsquo;s begin method to get an iterator pointing to the first element in the container. This iterator is then used to enumerate the elements, incrementing the iterator until it compares equal to the iterator returned by vector&amp;rsquo;s end method. For each iteration, the iterator is dereferenced with the resulting value assigned to the element variable. The beauty here is that using the &lt;strong&gt;for each&lt;/strong&gt; statement avoids many common errors related to buffer overruns and the like.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s get back to managed code. If the &lt;strong&gt;for each&lt;/strong&gt; statement has to support collections other than arrays, surely this leads to different implementations depending on the use of the statement. Consider the following example:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;Collections::ArrayList numbers(3);&lt;br /&gt;numbers.Add(1);&lt;br /&gt;numbers.Add(2);&lt;br /&gt;numbers.Add(3);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;for each (int element in %numbers)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console::WriteLine(element);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;As an aside, keep in mind that most of the Standard C++ Library containers that include a constructor taking a single integer typically set the initial size of the container, whereas the .NET collection types use this constructor to set the initial capacity.&lt;/p&gt;&lt;p&gt;So what does &lt;strong&gt;for each&lt;/strong&gt; do in this case? Well the ArrayList type implements the IEnumerable interface with its single GetEnumerator method. The &lt;strong&gt;for each&lt;/strong&gt; statement calls the GetEnumerator method to get an implementation of the IEnumerator interface that is then used to enumerate the collection. Let&amp;rsquo;s examine a simple implementation for this code:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .locals init (class [mscorlib]System.Collections.ArrayList numbers,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class [mscorlib]System.Collections.IEnumerator enumerator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Create the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; newobj instance void [mscorlib]System.Collections.ArrayList::.ctor(int32)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Populate the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance int32 [mscorlib]System.Collections.ArrayList::Add(object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pop&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Get the enumerator&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance class [mscorlib]System.Collections.IEnumerator &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [mscorlib]System.Collections.IEnumerable::GetEnumerator()&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _CONDITION&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONDITION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; brfalse.s _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// for each statements&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _CONDITION&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Well that looks good, but there&amp;rsquo;s something missing. Can you tell what it is? Since the for each statement is resulting in a new object being created by virtue of calling the GetEnumerator method, it is conceivable that this object requires deterministic cleanup to avoid resource leaks. The enumerator expresses this by implementing the IDisposable interface. Unfortunately, the compiler is not always capable of discerning this at compile time, though if the compiler has enough static type information there is certainly value in taking advantage of it to optimize the generated instructions. As it turns out, the enumerator provided by the ArrayList type does not implement the IDisposable interface. Of course this could change in future so &amp;ldquo;optimizing&amp;rdquo; your code for this type of thing is not a wise move. Compilers can use the &lt;strong&gt;isinst&lt;/strong&gt; instruction to determine whether the enumerator implements the IDisposable interface. Arguably this is an oversight in the design of the IEnumerable and IEnumerator interfaces.&lt;/p&gt;&lt;p&gt;To address this quirk, the generic IEnumerator interface introduced in version 2.0 of the .NET Framework makes it explicit by deriving from IDisposable so implementations have to provide a Dispose method even if it does nothing. This certainly simplifies matters for the caller. Collections.Generic.IEnumerator&amp;lt;T&amp;gt; is the return type for the GetEnumerator method from the Collections.Generic.IEnumerable&amp;lt;T&amp;gt; interface implemented by the new generic collection types. For compatibility with existing code, the enumerator implementations also implement the older, non-generic IEnumerator interface. Consider the following example:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;Collections::Generic::List&amp;lt;int&amp;gt; numbers(3);&lt;br /&gt;numbers.Add(1);&lt;br /&gt;numbers.Add(2);&lt;br /&gt;numbers.Add(3);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;for each (int element in %numbers)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console::WriteLine(element);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;In this case there is no question of whether the enumerator implements IDisposable. The only issue remaining is coming up with a reliable way of calling the Dispose method in the face of exceptions. Here&amp;rsquo;s a reasonable solution using the exception handling constructs discussed in &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/15/230167.aspx"&gt;part 5&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .locals init (class [mscorlib]System.Collections.Generic.&amp;#39;List`1&amp;#39;&amp;lt;int32&amp;gt; numbers,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class [mscorlib]System.Collections.Generic.&amp;#39;IEnumerator`1&amp;#39;&amp;lt;int32&amp;gt; enumerator)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Create the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.3&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; newobj instance void class [mscorlib]System.Collections.Generic.&amp;#39;List`1&amp;#39;&amp;lt;int32&amp;gt;::.ctor(int32)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Populate the array&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1 // value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance void class [mscorlib]System.Collections.Generic.&amp;#39;List`1&amp;#39;&amp;lt;int32&amp;gt;::Add(!0)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.2 // value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance void class [mscorlib]System.Collections.Generic.&amp;#39;List`1&amp;#39;&amp;lt;int32&amp;gt;::Add(!0)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.3 // value&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance void class [mscorlib]System.Collections.Generic.&amp;#39;List`1&amp;#39;&amp;lt;int32&amp;gt;::Add(!0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;// Get the enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc numbers&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance class [mscorlib]System.Collections.Generic.&amp;#39;IEnumerator`1&amp;#39;&amp;lt;!0&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class [mscorlib]System.Collections.Generic.&amp;#39;IEnumerable`1&amp;#39;&amp;lt;int32&amp;gt;::GetEnumerator()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _CONDITION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance bool class [mscorlib]System.Collections.Generic.&amp;#39;IEnumerator`1&amp;#39;&amp;lt;int32&amp;gt;::MoveNext()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; brfalse.s _LEAVE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _STATEMENTS:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance !0 class [mscorlib]System.Collections.Generic.&amp;#39;IEnumerator`1&amp;#39;&amp;lt;int32&amp;gt;::get_Current()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(int32)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _CONDITION&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _LEAVE:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc enumerator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance void [mscorlib]System.IDisposable::Dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; endfinally&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;With the comments and labels in place, it should be pretty easy to follow this code. Let&amp;rsquo;s walk through it quickly. Two local variables are required, one for the list and one for the enumerator. The strange-looking type names are to support generics in MSIL. &lt;strong&gt;&amp;#39;List`1&amp;#39;&lt;/strong&gt; indicates that the List type with a single type parameter is to be used. This distinguishes between generic types with the same name but with a different number of type parameters. The type list between the angle brackets denotes the actual types to use in runtime specialization. With the local variables defined, the next step is to create the list using the &lt;strong&gt;newobj&lt;/strong&gt; instruction and populate it by calling its Add method. Generics are primarily intended for creating type-safe collections. A good example of this is the code for adding the numbers to the list. The previous example used an ArrayList so the numbers first had to be boxed before adding them to the collection. In this case we can simply push the number on the stack and call the Add method. We just need to make sure to indicate the particular specialization we require. The Add method&amp;rsquo;s single parameter is &lt;strong&gt;!0&lt;/strong&gt; which indicates the zero-based type parameter. Now that the collection is ready, we can implement the actual for each loop. To begin enumerating we first get the IEnumerator&amp;lt;T&amp;gt; implementation from the collection and store it in out enumerator local variable. At this point we enter the protected range of instructions, calling the enumerator&amp;rsquo;s MoveNext method until it returns false. The &lt;strong&gt;finally&lt;/strong&gt; exception handler is then used to call the enumerator&amp;rsquo;s Dispose method.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=316014" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 7 – Casts and Conversions</title><link>http://weblogs.asp.net/kennykerr/archive/2004/10/19/introduction-to-msil-part-7-casts-and-conversions.aspx</link><pubDate>Tue, 19 Oct 2004 18:43:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:244670</guid><dc:creator>KennyKerr</dc:creator><slash:comments>4</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/10/19/introduction-to-msil-part-7-casts-and-conversions.aspx#comments</comments><description>&lt;p&gt;After a brief hiatus, I decided to post a few more parts of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;Introduction to MSIL&lt;/a&gt; series. &lt;/p&gt;&lt;p&gt;Casting and type conversion are often raised as topics of concern among programmers. It might be concerns over performance and safety or simply that the implications of casts and conversions are not well understood. In this part of the series I explore these concepts. I will primarily use C++ for illustrations as it is more descriptive in its language constructs related to casting. Of course we will also consider the CLI instructions that are ultimately generated.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Static Casts&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;When converting from a type with a small value space to a larger value space, an implicit cast can be employed as there is no danger of losing data. This is safe as long as the resulting value space is a superset of the smaller value space. Converting from a 32-bit integer to a 64-bit integer is guaranteed to be accurate, so compilers don&amp;rsquo;t require any explicit confirmation from the programmer. On the other hand, when converting from a larger type to a smaller type, it is possible for the data to be truncated; therefore compilers typically require confirmation in the form of a cast. This is referred to as a static cast, since only static type information is used in determining the conversion behavior. A static cast is often considered dangerous, as the compiler places the responsibility of ensuring the safety of the cast squarely in the hands of the programmer. Consider the following C++ code:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;Int32 small = 123;&lt;br /&gt;Int64 big = small;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;small = static_cast&amp;lt;Int32&amp;gt;(big);&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Conversion from the small variable to the big variable is implicit but conversion from big to small requires the &lt;strong&gt;static_cast&lt;/strong&gt; operator to avoid a compiler warning regarding possible loss of data. Although static casts can and should be considered dangerous, the compiler goes to great lengths to ensure that it is at least in the realm of possibility that the cast will actually be correct at runtime. It does this by considering the static type information, and in the case of user-defined types, whether there are any conversion operators defined. All this is determined at compile-time. Consider the following representation in MSIL:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.locals init (int32 small,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int64 big)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;// Int32 small = 123;&lt;br /&gt;ldc.i4.s 123&lt;br /&gt;stloc small&lt;br /&gt;&amp;nbsp;&lt;br /&gt;// Int64 big = small;&lt;br /&gt;ldloc small&lt;br /&gt;conv.i8&lt;br /&gt;stloc big&lt;br /&gt;&amp;nbsp;&lt;br /&gt;// small = static_cast&amp;lt;Int32&amp;gt;(big);&lt;br /&gt;ldloc big&lt;br /&gt;conv.i4&lt;br /&gt;stloc small&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;ldc.i4.s &lt;/strong&gt;instruction pushes a 4 byte (32-bit) integer with a value of 123 onto the stack. This is then stored in the small local variable using the &lt;strong&gt;stloc&lt;/strong&gt; instruction. To assign the value of the small variable to the big variable, the value is first pushed onto the stack using the &lt;strong&gt;ldloc&lt;/strong&gt; instruction. The &lt;strong&gt;conv.i8&lt;/strong&gt; instruction then converts the value to an 8 byte (64-bit) integer. This is then popped off the stack and stored in the big local variable using the &lt;strong&gt;stloc&lt;/strong&gt; instruction. Finally, to convert the value of the big variable to the small variable again, the value stored in the big local variable is pushed onto the stack and the 8 byte value on the stack is converted to a 4 byte value using the &lt;strong&gt;conv.i4&lt;/strong&gt; instruction. This is then stored in the small local variable using the &lt;strong&gt;stloc&lt;/strong&gt; instruction. &lt;/p&gt;&lt;p&gt;As you can see, MSIL does not make a distinction between implicit and explicit conversions. Everything is explicit. Overflow protection, however, needs to be requested directly, as by default&amp;nbsp;no checking&amp;nbsp;is provided. In the code above, no provision is made for overflow. This code happens to be safe because we know it to be so, but if the value stored in big was too large to be stored in a 4 byte integer, it would simply overflow with no warning at runtime.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Checked Conversions&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;To detect overflow errors, you can simply replace the &lt;strong&gt;conv.i4&lt;/strong&gt; instruction in the previous example with the &lt;strong&gt;conv.ovf.i4&lt;/strong&gt; instruction. If the value on the stack is too large to be represented by the specified type, an OverflowException object is thrown. The C++/CLI language design, introduced in Visual C++ 2005, does not yet provide a language feature to request conversion with overflow checking. A feature is being considered to add a &lt;strong&gt;checked&lt;/strong&gt; keyword, similar to the one provided by C#:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;checked&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int small = 123;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; long big = small;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; small = (int) big;&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Any arithmetic operations and conversions in a &lt;strong&gt;checked&lt;/strong&gt; block or expression will include overflow-checking. As mentioned above, the &lt;strong&gt;conv.&amp;lt;type&amp;gt;&lt;/strong&gt; set of instructions are replaced by &lt;strong&gt;conv.ovf.&amp;lt;type&amp;gt;&lt;/strong&gt;. Other instructions that could result in overflow also have corresponding checked versions. For example the &lt;strong&gt;add&lt;/strong&gt; instruction, described in &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/07/226300.aspx"&gt;part 2&lt;/a&gt;, has corresponding &lt;strong&gt;add.ovf&lt;/strong&gt; and &lt;strong&gt;add.ovf.un&lt;/strong&gt; instructions for checked addition of signed and unsigned values respectively.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Dynamic Casts&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Static casts can also be used to cast up a class hierarchy, in effect performing a cast of a polymorphic type but making an assumption that the cast will always succeed at runtime. This is useful to avoid the cost of a run-time type check, assuming it is safe. Of course, this is generally a dangerous assumption to make.&lt;/p&gt;&lt;p&gt;Dynamic casts are used to allow the determination of whether the cast is valid to be deferred to run-time. Of course this only makes sense with polymorphic types. As with static casts, the compiler tries to ensure that it is at least plausible that the cast may succeed. Trying to dynamically cast from an integer to a House object will be caught by the compiler and flagged as an error. Consider the following C++ code. Assume BeachHouse and Townhouse are subclasses of House.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;House^ house = gcnew BeachHouse;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;if (nullptr != dynamic_cast&amp;lt;BeachHouse^&amp;gt;(house))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console::WriteLine(&amp;quot;It&amp;#39;s a beach house!&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;if (nullptr != dynamic_cast&amp;lt;Townhouse^&amp;gt;(house))&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console::WriteLine(&amp;quot;It&amp;#39;s a townhouse!&amp;quot;);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;This code will compile perfectly without the compiler knowing whether the casts will succeed. Both casts require a run-time type check to determine whether the house is in fact a BeachHouse or a Townhouse. &lt;strong&gt;dynamic_cast&lt;/strong&gt; returns a &lt;strong&gt;nullptr&lt;/strong&gt;, the C++ representation for a null pointer or handle, if the cast cannot be performed. Let&amp;rsquo;s see how we can represent this in MSIL:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.locals init (class House house)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;newobj instance void BeachHouse::.ctor()&lt;br /&gt;stloc house&lt;br /&gt;&amp;nbsp;&lt;br /&gt;ldloc house&lt;br /&gt;isinst BeachHouse&lt;br /&gt;ldnull&lt;br /&gt;&amp;nbsp;&lt;br /&gt;beq.s _TOWN_HOUSE&lt;br /&gt;&amp;nbsp;&lt;br /&gt;ldstr &amp;quot;It&amp;#39;s a beach house!&amp;quot;&lt;br /&gt;call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_TOWN_HOUSE:&lt;br /&gt;&amp;nbsp;&lt;br /&gt;ldloc house&lt;br /&gt;isinst TownHouse&lt;br /&gt;ldnull&lt;br /&gt;&amp;nbsp;&lt;br /&gt;beq.s _CONTINUE&lt;br /&gt;&amp;nbsp;&lt;br /&gt;ldstr &amp;quot;It&amp;#39;s a town house!&amp;quot;&lt;br /&gt;call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Having read through this series thus far, this code should be pretty clear. A BeachHouse object is created and a reference to it is stored as a local variable. The dynamic cast is performed by pushing the reference onto the stack and using the &lt;strong&gt;isinst&lt;/strong&gt; instruction to do the type check. The &lt;strong&gt;isinst&lt;/strong&gt; instruction evaluates whether the reference on the stack is a BeachHouse or a subclass of the BeachHouse type. If it is, then the reference is cast to the type defined in the &lt;strong&gt;isinst&lt;/strong&gt; instruction and pushed onto the stack. Otherwise the value null is pushed onto the stack. The expression for the if statement is constructed by pushing a null reference onto the stack and using the &lt;strong&gt;beq.s&lt;/strong&gt; instruction to transfer control to the target if &lt;strong&gt;isinst&lt;/strong&gt; also pushed null onto the stack. The same type check and conditional branching is done for the Townhouse type, with execution ultimately continuing on.&lt;/p&gt;&lt;p&gt;If your application assumes that the dynamic cast must always succeed for the program to be correct, but you don&amp;rsquo;t want to resort to a static cast to ensure correctness in the exceptional case, you can employ the &lt;strong&gt;castclass&lt;/strong&gt; instruction in place of the &lt;strong&gt;isinst&lt;/strong&gt; instruction. The &lt;strong&gt;castclass&lt;/strong&gt; instruction performs the same type check, but instead of pushing null onto the stack if the type check fails, it throws an InvalidCastException object. If this is the behavior you are looking for, you can use the &lt;strong&gt;safe_cast&lt;/strong&gt; operator in C++ or a simple (C-style) cast in C#. &lt;/p&gt;&lt;p&gt;Read part 8 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/12/15/316014.aspx"&gt;The for each Statement&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=244670" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 6 – Common Language Constructs</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx</link><pubDate>Thu, 23 Sep 2004 17:04:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:233471</guid><dc:creator>KennyKerr</dc:creator><slash:comments>2</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx#comments</comments><description>&lt;p&gt;In parts 1 through 5 of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;Introduction to MSIL&lt;/a&gt; series we focused on MSIL and the constructs it provides for writing managed code. In the next few sections we are going to examine some common language features that are not intrinsic to instruction-based languages like MSIL. Understanding the intermediate language instructions that are generated for common, programming language statements is critical to acquiring an instinct for the performance characteristics of your code as well as to more easily track down subtle bugs.&lt;/p&gt;&lt;p&gt;In this part we are going to look at some common constructs that are present in many languages. I will be expressing simple examples in C# although the explanations are common to many programming languages that offer the same general constructs. As I am trying to explain a general principle, I may not always present the exact code that a given compiler may produce. The point is to learn more about what compilers generate in general. I encourage you to compare the instructions generated by different compilers using tools like &lt;a href="http://msdn.microsoft.com/library/en-us/cptools/html/cpconMSILDisassemblerIldasmexe.asp"&gt;ILDASM&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Programming languages like C and C++ enabled much more rapid development of software compared with classic assembly language programming. A number of rich constructs played a significant part in providing this productivity. Concepts like expressions, selection statements (e.g. if and switch), and iteration statements (e.g. while and for) are what makes these portable languages so powerful. Even more productivity was gained by introducing concepts like objects, but before objects were even considered, expressions and statements provided enormous benefit to the assembly language programmer struggling to build large applications and operating systems. Let&amp;rsquo;s look at some of these statements.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The if-else Statement&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Consider the following simple method that checks that its argument is not null before proceeding.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;void Send(string message)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (null == message)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException(&amp;quot;message&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* impl */&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&lt;br /&gt;The &lt;strong&gt;if&lt;/strong&gt; statement looks innocent enough. If the expression is true, execution enters the scope block and an exception is thrown. If the expression is false, execution jumps to the first statement following the &lt;strong&gt;if&lt;/strong&gt; statement. There&amp;rsquo;s enough going on here that I will leave the &lt;strong&gt;else&lt;/strong&gt; clause as an exercise for the reader.&lt;/p&gt;&lt;p&gt;Even if you have never used C# before, this code should be pretty clear (assuming you&amp;rsquo;re a programmer). So how does the compiler turn this innocent little &lt;strong&gt;if&lt;/strong&gt; statement into something the runtime will understand? As with most programming tasks, there are a number of ways to solve the problem. &lt;/p&gt;&lt;p&gt;In many cases it is necessary for a compiler to create temporary objects. Expressions are a common source of temporary objects. In practice, compilers avoid creating temporaries as much as possible. Assuming a non-optimizing compiler you could imagine the compiler turning the code above into something like this. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;bool isNull = null == message;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;if (isNull)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException(&amp;quot;message&amp;quot;);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;This is not to say that an optimizing compiler would not use temporary objects in this manner. Temporary objects can often help to generate more efficient code depending on the circumstance. Here the result of the expression is first evaluated to a boolean value. This value is then passed to the &lt;strong&gt;if &lt;/strong&gt;statement. This is not all that different from the previous example, but after reading the last 5 parts of this series it should be clear why this is much more appealing to an instruction-based language. It&amp;rsquo;s all about breaking down statements and expressions into simple instructions that can be executed one by one. Let&amp;rsquo;s consider one implementation of the Send method.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method void Send(string message)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldnull&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldarg message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ceq&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ceq&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; brtrue.s _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;message&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _CONTINUE: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* impl */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;If you&amp;rsquo;ve been following along with this series you should be able to understand much of this method declaration. Let&amp;rsquo;s step through it quickly. The temporary object that the compiler might generate silently is made explicit in MSIL, although it is not named and lives very briefly on the stack. (I guess whether it is actually explicit is debatable.) Can you spot it? First we compare message to null. The &lt;strong&gt;ceq&lt;/strong&gt; instruction pops two values off the stack, compares them, and then pushes 1 onto the stack if they are equal or 0 if they are not (this is the temporary). The code may seem overly complicated. The reason is that MSIL does not have a &lt;em&gt;cneq&lt;/em&gt;, or compare-not-equal-to, instruction. So we first compare message to null then compare the result to zero, effectively negating the first comparison. More on this in a moment.&lt;/p&gt;&lt;p&gt;Now that we&amp;rsquo;ve got a handle on the expression result, the &lt;strong&gt;brtrue.s&lt;/strong&gt; instruction provides the conditional branching you would expect from an &lt;strong&gt;if&lt;/strong&gt; statement. It transfers control to the given target if the value on the stack is non-zero, thereby skipping over the &lt;strong&gt;if&lt;/strong&gt; clause&amp;rsquo;s logical scope block. &lt;/p&gt;&lt;p&gt;Of course there is more than one way to skin a cat. The example above is very similar to what the C# compiler that I am using generates, although it uses an explicit temporary local variable to store the result of the expression. This implementation seems a bit awkward. Ultimately it does not matter too much as the JIT compiler can probably optimize away any differences. Nevertheless it is a useful exercise to see how we can simplify this implementation. The first thing we can attempt is to reduce the number of comparisons. I mentioned that there is no matching not-equal-to version of the &lt;strong&gt;ceq&lt;/strong&gt; instruction. On the other hand there is a branch-on-false version of the &lt;strong&gt;brtrue.s&lt;/strong&gt; instruction. Quite predictably, it is called &lt;strong&gt;brfalse.s&lt;/strong&gt;. Using the &lt;strong&gt;brfalse.s&lt;/strong&gt; instruction completely removes the need for the second comparison. &lt;/p&gt;&lt;p&gt;Finally, as a C++ programmer you would expect the compiler to use the equality operator, since one of the operands is a System.String type which has an equality operator defined for it, and this is exactly what the C++ compiler does. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method void Send(string message)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldnull&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldarg message&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call bool string::op_Equality(string, string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; brfalse.s _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;message&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _CONTINUE: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* impl */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Ultimately the JIT compiler optimizes the code as best it can, including inlining methods where appropriate. You should not be surprised if these two implementations result in the same machine code at the end of the day. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;The for Statement&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Before we delve into the implementation of the &lt;strong&gt;for&lt;/strong&gt; statement, commonly referred to as &lt;em&gt;for loops&lt;/em&gt;, lets quickly review how the &lt;strong&gt;for&lt;/strong&gt; statement works. If your background is in Visual Basic or even C# you may not be all that familiar with this extremely useful statement. Even C++ programmers are encouraged to avoid the &lt;strong&gt;for&lt;/strong&gt; statement for common iterations in favor of the safer std::for_each algorithm from the Standard C++ Library. There are however, many interesting applications of the for loop that have nothing to do with iterating over a container from beginning to end. &lt;/p&gt;&lt;p&gt;The following simple pseudo code illustrates the construction of a for statement.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;for ( initialization expression ; condition expression ; loop BLOCKED EXPRESSION&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statements&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;for&lt;/strong&gt; statement consists of three semi-colon delimited expressions followed by a scope block. (Don&amp;rsquo;t get me started on for statements without scope blocks.) You can use any expressions you wish as long as the condition expression results in a value that can be interpreted to mean either true or false. The initialization expression is executed first and exactly once. It is typically used to initialize loop indices for iteration or any other variables required by the for statement. The condition expression is executed next and is executed before each subsequent loop. If the expression evaluates to true, the scope block will be entered. If the expression evaluates to false, control is passed to the first statement following the for statement. The loop expression is executed after every iteration. This can be used to increment loop indices or move cursors or anything else that might be appropriate. Following the loop expression, the condition expression is evaluated again and so on and so forth. For a more complete description, please consult your programming language documentation. Here is a simple example that will write the numbers zero through nine to any trace listeners you have set up.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;for (int index = 0; 10 != index; ++index)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.WriteLine(index);&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;We have already spoken about how an &lt;strong&gt;if &lt;/strong&gt;statement might be implemented in MSIL. Lets now make use of that knowledge to deconstruct the &lt;strong&gt;for&lt;/strong&gt; statement into something simpler to interpret by a computer while still using C#.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int index = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto _CONDITION;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_LOOP:&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ++index;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONDITION:&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (10 != index)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // for statements&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.WriteLine(index);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto _LOOP;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt;&lt;p&gt;That looks nothing like the &lt;strong&gt;for&lt;/strong&gt; statement! Here I use the infamous &lt;strong&gt;goto&lt;/strong&gt;, more generally referred to as a branch instruction. Branching is inevitable in languages that don&amp;rsquo;t support selection and iteration statements. It serves no purpose in languages like C++ and C# other than to obfuscate the code. (If you&amp;rsquo;re a major supporter of the goto statement, please don&amp;rsquo;t feel the need to share that with me. Feel free to talk about its merits on your own blog.) Code generators however often use goto statements as it is a lot simpler for a code generator to use than to construct the expressions for a &lt;strong&gt;for&lt;/strong&gt; statement for example.&lt;/p&gt;&lt;p&gt;By following the branching in the code example above you should be able to see how we construct the &lt;strong&gt;for&lt;/strong&gt; statement semantics by executing the condition and then jumping up to the loop expression to conditionally loop again. Now let&amp;rsquo;s consider how we can implement this in MSIL.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .locals init (int32 index)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _CONDITION&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_LOOP:&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc index&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;_CONDITION:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.s 10&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; beq _CONTINUE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // for statements&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [System]System.Diagnostics.Debug::WriteLine(object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; br.s _LOOP&lt;br /&gt;&amp;nbsp;&lt;br /&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;After initializing the index local variable we branch to the _CONDITION label. To evaluate the condition I pushed the value 10 onto the stack followed by the index value. The &lt;strong&gt;beq&lt;/strong&gt;, or branch on equal, instruction pops two values off the stack and compares them. If they are equal it transfers control to the _CONTINUE label thereby ending the loop; otherwise control continues through the &amp;lsquo;statements&amp;rsquo; in the for loop. To write the index to the debug trace listener I push the index onto the stack, box it and call the static WriteLine method on the System.Diagnostics.Debug reference type from the System assembly. Following this, the&lt;strong&gt; br.s&lt;/strong&gt; instruction is used to transfer control to the loop expression for the next iteration. &lt;/p&gt;&lt;p&gt;Read part 7 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/10/19/244670.aspx"&gt;Casts and Conversions&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=233471" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 5 – Exception Handling</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/15/introduction-to-msil-part-5-exception-handling.aspx</link><pubDate>Wed, 15 Sep 2004 23:58:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:230167</guid><dc:creator>KennyKerr</dc:creator><slash:comments>4</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/15/introduction-to-msil-part-5-exception-handling.aspx#comments</comments><description>&lt;p&gt;In this part of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;Introduction to MSIL&lt;/a&gt; series I will introduce the constructs that the CLI provides for exception handling.&lt;/p&gt;&lt;p&gt;A try block is used to protect a range of instructions. If an exception is thrown by one of the instructions in the protected block, or by any method called directly or indirectly within the protected block, control is transferred to an appropriate exception handler. A try block is declared with the &lt;strong&gt;.try &lt;/strong&gt;directive.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* protected code */&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;&amp;lt;exception handler&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;_CONTINUE:&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The last instruction in the try block is the &lt;strong&gt;leave.s&lt;/strong&gt; instruction which transfers control to the _CONTINUE label. The &lt;strong&gt;leave.s&lt;/strong&gt; instruction ensures that the evaluation stack is emptied and that the appropriate finally blocks are executed. It follows that if control leaves the protected block by some other means, that an exception was thrown. The exception handler must immediately follow the try block.&lt;/p&gt;&lt;p&gt;The CLI offers four different kinds of handlers that you can employ to construct the error handling semantics that you require for your programming language or application. Let&amp;rsquo;s examine each one individually.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Catch&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The catch exception handler, or catch block, has to be the most well-known form of exception handling, since it is provided directly by C++ as well as C#. A catch block is declared with the &lt;strong&gt;catch&lt;/strong&gt; keyword. The catch clause includes the type of exception that the handler is willing to catch as well as the block of code to transfer control to, given a matching exception object. Catch blocks can also be chained together after a single try block for convenience. The first catch clause with a matching exception type will be chosen as the handler. Consider this example.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;I&amp;#39;m not a number&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ldnull&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ldstr &amp;quot;123&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call int32 [mscorlib]System.Int32::Parse(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;catch [mscorlib]System.ArgumentNullException&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance string [mscorlib]System.Exception::get_Message()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;catch [mscorlib]System.FormatException&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance string [mscorlib]System.Exception::get_Message()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Here we ask the In32::Parse method to parse &amp;quot;I&amp;#39;m not a number&amp;quot;, which predictably throws a FormatException. The first catch handler is never given an opportunity to execute. The FormatException handler dutifully writes a message describing the exception to the console and then calls the &lt;strong&gt;leave.s &lt;/strong&gt;instruction to transfer control to the _CONTINUE label. Where was the exception object? The runtime ensure that a reference to the exception is pushed onto the stack before the handler is invoked. You can experiment by commenting out the &lt;strong&gt;ldstr&lt;/strong&gt; instruction in the try block and un-commenting the &lt;strong&gt;ldnull&lt;/strong&gt; instruction. This will push a null reference onto the stack and result in an ArgumentNullException instance being thrown by the Parse method.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Filter&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The filter exception handler is a strange construct for a C++ programmer like me. Instead of matching on an exception type, the filter handler provides a scope block where it can evaluate whether it wants to handle the exception. It indicates to the runtime that it wants to handle the exception by pushing a value of 1 onto the stack. If it decides not to handle the exception it pushes a value of 0 onto the stack. Following the &amp;ldquo;evaluation&amp;rdquo; block is the handler block that contains the code that will handle the exception. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ldstr &amp;quot;I&amp;#39;m not a number&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldnull&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ldstr &amp;quot;123&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call int32 [mscorlib]System.Int32::Parse(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;filter&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;filter evaluation\n\t&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::Write(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance string [mscorlib]System.Exception::get_Message()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldc.i4.1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; endfilter&lt;br /&gt;}&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;filter handler\n\t&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::Write(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; callvirt instance string [mscorlib]System.Exception::get_Message()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The try block will result in an ArgumentNullException exception because a null reference is pushed onto the stack as an argument to the Int32::Parse method. &lt;/p&gt;&lt;p&gt;The filter is then given a chance to determine whether it wants to handle the exception. In this case it simply writes the error message to the console and then pushes the value 1 onto the stack, using the &lt;strong&gt;ldc.i4.1&lt;/strong&gt; instruction, to indicate that it wants to handle the exception. The endfilter instruction is called to return from the filter clause.&lt;/p&gt;&lt;p&gt;The filter handler block is then called to handle the exception. Notice that both the evaluation and handler blocks can access the exception in flight by popping it off of the stack. Keep in mind that you can throw any reference type so don&amp;rsquo;t assume that the object reference you pop off of the stack in the filter handler is an instance of System.Exception. This is not a problem for the catch handler since you will know the type of the exception object.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Finally&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The finally exception handler should be recognized by C# programmers and C++ programmers familiar with Structured Exception Handling (SEH). A finally block associated with a try block is always executed, regardless of whether control leaves the protected try block through normal means, using the &lt;strong&gt;leave.s &lt;/strong&gt;instruction, or as a result of an exception, using the &lt;strong&gt;throw&lt;/strong&gt; instruction. It provides a reliable mechanism of ensuring a certain block of code is always run for those languages that do not provide destructors, such as C and C#. Although the C programming language does not target the CLI, SEH is used often enough that the Microsoft C/C++ compiler provides the &lt;strong&gt;__finally &lt;/strong&gt;keyword for the same reason.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* protected code */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* cleanup code */&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; endfinally&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Fault&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The fault exception handler is similar to the finally block except that it is invoked only if it&amp;rsquo;s associated try block is left as a result of an exception. After the fault handler has been given an opportunity to execute, the exception continues on its way in search or a handler that is willing to catch it.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* protected code */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; leave.s _CONTINUE&lt;br /&gt;}&lt;br /&gt;fault&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* cleanup code */&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; endfault&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;With that brief introduction to exception handling out of the way, it is time to change gears a bit and talk about how this all relates to popular programming languages like C# and C++/CLI. &lt;/p&gt;&lt;p&gt;Read part 6 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/23/233471.aspx"&gt;Common Language Constructs&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=230167" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 4 – Defining Type Members</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/12/introduction-to-msil-part-4-defining-type-members.aspx</link><pubDate>Sun, 12 Sep 2004 05:03:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:228354</guid><dc:creator>KennyKerr</dc:creator><slash:comments>1</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/12/introduction-to-msil-part-4-defining-type-members.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/09/227316.aspx"&gt;Part 3&lt;/a&gt; of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;MSIL series&lt;/a&gt;, I introduced the basic syntax for defining types. Using the &lt;strong&gt;.class&lt;/strong&gt; directive, you can define reference types and value types. Choosing the type attributes correctly, you can exercise complete control over the definition of your type.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class abstract Kerr.Sample.Object&lt;br /&gt;{&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;In this installment, we are going to explore how to declare members of a type. To simplify the samples, I may omit the class definitions at times and simply focus on defining the members. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Constructors&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s begin with initializers, known as constructors in languages like C++ and C#. CLI supports both type initializers and instance initializers. Type initializers are a very handy thing and address many of the multithreading challenges you encounter when implementing a singleton in native C++. A type initializer is run exactly once for a given type and the runtime guarantees that no methods of the type will be accessible before the type initializer completes. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method static void .cctor()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;.cctor&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method public void .ctor()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldarg.0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call instance void [mscorlib]System.Object::.ctor()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;.ctor&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;.cctor&lt;/strong&gt; and &lt;strong&gt;.ctor&lt;/strong&gt; are known as special method names. A type initializer, which is optional, is defined as a static method named &lt;strong&gt;.cctor&lt;/strong&gt; with no return value. Type initializers are called static constructors in the C++/CLI and C# languages.&lt;/p&gt;&lt;p&gt;An instance initializer, more commonly referred to simply as a constructor, initializes an instance of a type. A constructor is defined as an instance method named &lt;strong&gt;.ctor&amp;nbsp;&lt;/strong&gt;also with not return value.&amp;nbsp;A constructor is called when an instance is created using the &lt;strong&gt;newobj&lt;/strong&gt; instruction. Here is an example.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.locals (class TypeName obj)&lt;br /&gt;newobj void TypeName::.ctor()&lt;br /&gt;stloc obj&lt;/font&gt;&lt;/p&gt;&lt;p&gt;When executed, it will result in the following written to the console, assuming the constructors defined above.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.cctor&lt;br /&gt;.ctor&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;newobj &lt;/strong&gt;instruction allocates a new instance of the type and initializes all its fields to the type-equivalent of zero. Then it calls the particular constructor, disambiguated by the signature, ensuring that the first (zero-based) argument refers to the newly created instance. Once the constructor completes, an object reference is pushed onto the stack for access by the caller.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Methods&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Although the CLI defines constructors and properties in terms of methods (with some extra metadata for properties), in this section we are going to look at methods in the sense of C++ member functions or C# methods. Of course most of what is said of methods, also applies to instance constructors and property getters and setters. Virtually all of the interesting things that you can do with methods are controlled by method attributes. There are some common scenarios programmers expect so lets cover a few of them.&lt;/p&gt;&lt;p&gt;Static methods are defined using the &lt;strong&gt;static&lt;/strong&gt; attribute. Static methods, as you would expect, are associated with a type but not an instance. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method static void StaticMethod() { /* impl */ }&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Instance methods simply use the &lt;strong&gt;instance &lt;/strong&gt;attribute in place of the &lt;strong&gt;static &lt;/strong&gt;attribute. The IL Assembler assumes &lt;strong&gt;instance &lt;/strong&gt;as the default so you rarely need to specify it explicitly for method declarations. &lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method void InstanceMethod() { /* impl */ }&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The opposite is true when calling methods. The &lt;strong&gt;call&lt;/strong&gt; instruction assumes a static method unless you specify otherwise. Here is an example of calling both methods.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;call void TypeName::StaticMethod()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc obj&lt;br /&gt;call instance void TypeName::InstanceMethod()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Remember to push the object reference pointing to your instance onto the stack before calling the instance method.&lt;/p&gt;&lt;p&gt;Virtual function calls are an important part of object-oriented design and the CLI provides a great deal of flexibility in controlling whether the static or dynamic type of the object will be used to service the call, as well as how this behavior can be overridden in subclasses. When I refer to the static and dynamic type in this context I am referring to it in the C++ sense of the static type known at compile time and the dynamic type determined at runtime. This is generally referred to as polymorphism. There are two aspects to the virtual function support that you need to keep in mind when programming in MSIL. The first is how you declare your instance methods to support virtual function invocation and the second is how you call the method. It should also go without saying that static methods are by definition not virtual.&lt;/p&gt;&lt;p&gt;A method is marked virtual by adding the &lt;strong&gt;virtual&lt;/strong&gt; attribute to the type header. Consider the following example.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class House&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method public virtual void Buy()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;House::Buy&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* etc */&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class TownHouse&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; extends House&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method public virtual void Buy()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;TownHouse::Buy&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* etc */&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The House type has a virtual method called Buy. The TownHouse type extends House and also has a virtual method with the same name. Because of this, TownHouse::Buy is said to override House::Buy. So how do we tell the runtime which method to pick? Obviously if I have a House instance I would like House::Buy to be called, but if I have a TownHouse instance I would like TownHouse::Buy to be called and, being a virtual method, I want this decision to be made at runtime when the actual type is known. So far I have used the &lt;strong&gt;call&lt;/strong&gt; instruction in a number of examples in this series. The call instruction invokes the specified method and will always call the same method regardless of the dynamic type of the object. The &lt;strong&gt;callvirt&lt;/strong&gt; instruction, on the other hand, allows the runtime to determine the specific virtual method implementation to invoke based on the actual type of the object. Consider the following example.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;newobj instance void House::.ctor()&lt;br /&gt;stloc house&lt;br /&gt;newobj instance void TownHouse::.ctor()&lt;br /&gt;stloc townHouse&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc house&lt;br /&gt;call instance void House::Buy()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc townHouse&lt;br /&gt;call instance void TownHouse::Buy()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc townHouse&lt;br /&gt;call instance void House::Buy()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc townHouse&lt;br /&gt;callvirt instance void House::Buy()&lt;/font&gt;&lt;/p&gt;&lt;p&gt;When executed, it will result in the following written to the console.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;House::Buy&lt;br /&gt;TownHouse::Buy&lt;br /&gt;House::Buy&lt;br /&gt;TownHouse::Buy&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The first call to the Buy method with the house reference invokes the House::Buy implementation since &lt;strong&gt;call&lt;/strong&gt; is only interested in the static, or compile-time, type. The second call to Buy with the townhouse reference invokes the TownHouse::Buy implementation for the same reason. The third call will once again invoke House::Buy despite the fact that the object reference points to a TownHouse. It should now be clear that using the &lt;strong&gt;call&lt;/strong&gt; instruction implies making a compile-time decision on which method to execute. The final method call uses the &lt;strong&gt;callvirt&lt;/strong&gt; instruction to invoke the virtual method House::Buy and since the object reference actually points to a TownHouse, the TownHouse::Buy method will be executed. To be clear, the runtime is not looking at the type of the local variable you declared but rather the type of the object being referenced. We could have stored a reference to a TownHouse in a House local variable and the TownHouse::Buy method would still have been called.&lt;/p&gt;&lt;p&gt;If you want to declare a virtual method but do not want to override an inherited virtual method with the same name, you can use the &lt;strong&gt;newslot&lt;/strong&gt; attribute on the new virtual method in the subclass. If you consider that virtual method invocation by the runtime is not concerned about method names then you should see how this is possible. Just think of &lt;strong&gt;newslot&lt;/strong&gt; as adding a new virtual function pointer to the vtbl for the given type. &lt;/p&gt;&lt;p&gt;CLI virtual methods are very interesting, especially when you consider how and to what extent they are exposed by C++/CLI and C#. This entry is getting long enough so I&amp;rsquo;ll save that discussion for another day.&lt;/p&gt;&lt;p&gt;Read part 5 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/15/230167.aspx"&gt;Exception Handling&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;script type="text/javascript"&gt;







&lt;!--
google_ad_client = "pub-2484098146130174";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel = "";
google_color_border = "6699CC";
google_color_bg = "003366";
google_color_link = "FFFFFF";
google_color_text = "AECCEB";
google_color_url = "AECCEB";
//--&gt;&lt;/script&gt;&lt;script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=228354" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 3 – Defining Types</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/09/introduction-to-msil-part-3-defining-types.aspx</link><pubDate>Thu, 09 Sep 2004 12:49:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:227316</guid><dc:creator>KennyKerr</dc:creator><slash:comments>8</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/09/introduction-to-msil-part-3-defining-types.aspx#comments</comments><description>&lt;p&gt;In this installment of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;MSIL series&lt;/a&gt;, I describe how types are defined. &lt;/p&gt;&lt;p&gt;Here is a minimal reference type called House. As I write this, we are looking for a house in &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/03/225537.aspx"&gt;British Columbia&lt;/a&gt;, so this was the first thing that came to mind.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class Kerr.RealEstate.House&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .method public void .ctor()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldarg.0 // push &amp;quot;this&amp;quot; instance onto the stack&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call instance void [mscorlib]System.Object::.ctor()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;This is a very simple type. Note that you must declare a constructor for a concrete reference type. Unlike languages like C# and C++, the IL assembler will not generate a constructor for you automatically. &lt;/p&gt;&lt;p&gt;Types are defined using the &lt;strong&gt;.class &lt;/strong&gt;directive followed by a type header. The &lt;strong&gt;class &lt;/strong&gt;keyword is used instead of the more intuitive &lt;em&gt;type &lt;/em&gt;for historical reasons. When you read &lt;strong&gt;class &lt;/strong&gt;in MSIL source code, just think &lt;em&gt;type&lt;/em&gt;. The type header consists of a number of type attributes followed by the name of the type you are defining. To define the equivalent of a C# static class in MSIL you can write the following.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class abstract sealed Kerr.RealEstate.MortgageCalculator&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* members */ &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;abstract &lt;/strong&gt;and &lt;strong&gt;sealed &lt;/strong&gt;are the type attributes. An abstract type cannot be instantiated and a sealed type cannot have sub-types. There are attributes to control visibility, such as &lt;strong&gt;public &lt;/strong&gt;and &lt;strong&gt;private&lt;/strong&gt;. There are attributes to control field layout, such as &lt;strong&gt;auto &lt;/strong&gt;and &lt;strong&gt;sequential&lt;/strong&gt;. For a complete list of attributes please consult the &lt;a href="http://msdn.microsoft.com/net/ecma/"&gt;CLI specification&lt;/a&gt;. Many attributes are applied automatically, which can save you a lot of typing. Fortunately these defaults are quite intuitive so you should become familiar with them quickly. As an example, extending the System.ValueType from the mscorlib assembly defines a value type. Since the CLI requires that value types be sealed, the IL assembler will automatically add this attribute for you. &lt;/p&gt;&lt;p&gt;The name of the type in the example above is Kerr.RealEstate.MortgageCalculator. The CLI does not recognize namespaces as a distinct concept. Rather the full type name is always used. The syntax shown above is only supported by the IL Assembler that ships with version 2.0 of the .NET Framework. If you are working with version 1.x then you need to group your namespace members with a &lt;strong&gt;.namespace &lt;/strong&gt;directive, as shown below. Note that this syntax is also supported in version 2.0.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.namespace Kerr.RealEstate&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .class abstract sealed MortgageCalculator&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* members */ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Following the type name you have the option of specifying the base type. The &lt;strong&gt;extend&lt;/strong&gt; keyword is used for this purpose. If no base type is specified, the IL assembler will add the extend clause to make the type inherit from the System.Object type from the mscorlib assembly, resulting in a reference type. And finally, the type header can provide a list of interfaces that the type and its descendants will implement and satisfy, becoming the interfaces of the type.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class Kerr.RealEstate.RoomList&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; extends [System.Windows.Forms]System.Windows.Forms.ListView&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; implements Kerr.IView&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* members */&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;In this example, the Kerr.RealEstate.RoomList type has System.Windows.Forms.ListView, defined in the System.Windows.Forms assembly, as its base type. Keep in mind that the CLI requires that every user-defined type extend exactly one other type. The RoomList type also implements the Kerr.IView interface type.&lt;/p&gt;&lt;p&gt;With this basic introduction to type definitions, you should now be able to start defining more interesting types. To define an interface, simply use the &lt;strong&gt;interface&lt;/strong&gt; attribute in your type header. If you want a value type, known as a struct in C#, simply extend the System.ValueType type from the mscorlib assembly. Now you should be able to see why the &lt;strong&gt;.class&lt;/strong&gt; directive is perhaps not the best name for it.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class interface Kerr.IView&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* members */ &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.class Kerr.RealEstate.HouseData&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; extends [mscorlib]System.ValueType&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /* members */&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Read part&amp;nbsp;4 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/12/228354.aspx"&gt;Defining Type Members&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;script type="text/javascript"&gt;







&lt;!--
google_ad_client = "pub-2484098146130174";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel = "";
google_color_border = "6699CC";
google_color_bg = "003366";
google_color_link = "FFFFFF";
google_color_text = "AECCEB";
google_color_url = "AECCEB";
//--&gt;&lt;/script&gt;&lt;script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=227316" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 2 – Using Local Variables</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/07/introduction-to-msil-part-2-using-local-variables.aspx</link><pubDate>Tue, 07 Sep 2004 13:34:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:226300</guid><dc:creator>KennyKerr</dc:creator><slash:comments>6</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/07/introduction-to-msil-part-2-using-local-variables.aspx#comments</comments><description>&lt;p&gt;In part 2 of the &lt;a href="http://weblogs.asp.net/kennykerr/category/7140.aspx"&gt;Introduction to MSIL&lt;/a&gt; series, I will be exploring the use of local variables. Without variables, programs would not be very interesting. To illustrate the use of variables, let&amp;rsquo;s write a simple program to add numbers together.&lt;/p&gt;&lt;p&gt;In an MSIL method, variables are declared using the &lt;strong&gt;.locals&lt;/strong&gt; directive.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.locals init (int32 first,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 second,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 result)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;This statement declares three local variables for the current method. In this case they all happen to be of type &lt;strong&gt;int32&lt;/strong&gt;, which is a synonym for the System.Int32 type. &lt;strong&gt;init&lt;/strong&gt; specifies that the variables must be initialized to the default values for their respective types. It is also possible to omit the variable names. In that case you would refer to the variables by their zero-based index in the declaration. Of course, using variable names improves readability.&lt;/p&gt;&lt;p&gt;Before we continue, I want to make sure that it is clear how the stack is used explicitly in MSIL. When you want to pass values to an instruction, those values need to be pushed onto the stack. To read those values, the instruction must pop them off the stack. Similarly when calling a method, you need to push the object reference (if any) onto the stack followed by each argument that you wish to pass to the method. In the process of invoking the method, all the arguments as well as the object reference will be popped off the stack. To push a value onto the stack, use the &lt;strong&gt;ldloc&lt;/strong&gt; instruction indicating the variable that holds the value. To pop a value off the stack, use the &lt;strong&gt;stloc &lt;/strong&gt;instruction specifying the variable you wish to store the value in. Also keep in mind that values (based on value types) are stored directly on the stack, but objects (instances of reference types) are not since the CLI does not allow reference types to be allocated on the stack. Rather references to objects are stored on the stack. This is analogous to a native C++ object allocated on the heap with a pointer to it stored on the stack. Keep the stack in your mind as you read this series on MSIL. It should help you understand why values are continually pushed and popped on and off the stack. &lt;/p&gt;&lt;p&gt;The next step is to get the numbers from the user.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldstr &amp;quot;First number: &amp;quot;&lt;br /&gt;call void [mscorlib]System.Console::Write(string)&lt;br /&gt;call string [mscorlib]System.Console::ReadLine()&lt;br /&gt;call int32 [mscorlib]System.Int32::Parse(string)&lt;br /&gt;stloc first&lt;/font&gt;&lt;/p&gt;&lt;p&gt;As I mentioned in &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/07/226232.aspx"&gt;Part 1&lt;/a&gt;, the &lt;strong&gt;ldstr&lt;/strong&gt; instruction pushes the string onto the stack and the &lt;strong&gt;call&lt;/strong&gt; instruction invokes the Write method, popping its argument off the stack. The next &lt;strong&gt;call&lt;/strong&gt; instruction invokes the ReadLine method which returns a string. The returned string is pushed onto the stack and since it is already there, we simply call the Int32::Parse method which pops the string off the stack and pushes the int32 equivalent on. Note that I am omitting any error handling for the sake of clarity. The &lt;strong&gt;stloc&lt;/strong&gt; instruction then pops the value off the stack and stores it in the local variable named &amp;#39;first&amp;#39;. Getting the next number from the user works the same way except that the value is stored in the local variable named &amp;#39;second&amp;#39;.&lt;/p&gt;&lt;p&gt;Now that we have read the two numbers from standard input, it is time to add them up. The &lt;strong&gt;add&lt;/strong&gt; instruction can be used for this purpose. &lt;/p&gt;&lt;p&gt;ldloc first&lt;br /&gt;ldloc second&lt;br /&gt;add&lt;br /&gt;stloc result&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;add&lt;/strong&gt; instruction pops two values off the stack and calculates the sum. To push the values of the local variables onto the stack, we use the &lt;strong&gt;ldloc&lt;/strong&gt; instruction. When the &lt;strong&gt;add&lt;/strong&gt; instruction completes, it pushes the result onto the stack and the program pops the value off the stack and stores it in a variable named &amp;#39;result&amp;#39; using the &lt;strong&gt;stloc&lt;/strong&gt; instruction.&lt;/p&gt;&lt;p&gt;The final step is to display the result to the user.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldstr &amp;quot;{0} + {1} = {2}&amp;quot;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc first&lt;br /&gt;box int32&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc second&lt;br /&gt;box int32&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ldloc result&lt;br /&gt;box int32&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;call void [mscorlib]System.Console::WriteLine(string, object, object, object)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;We use the WriteLine overload that takes a format string followed by three object arguments. Each argument to the WriteLine method must be pushed onto the stack one by one. Since the numbers are stored as int32 value types, we need to box each value; otherwise the method signature won&amp;rsquo;t match.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;ldloc&lt;/strong&gt; instruction pushes each argument onto the stack. The &lt;strong&gt;box&lt;/strong&gt; instruction is then used for each int32 argument. Boxing involves popping the value off the stack, constructing a new object containing a copy of the value and then pushing a reference to the object onto the stack. &lt;/p&gt;&lt;p&gt;Here is the complete program.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method static void main()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .entrypoint&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 4&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .locals init (int32 first,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 second,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int32 result)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;First number: &amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::Write(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call string [mscorlib]System.Console::ReadLine()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call int32 [mscorlib]System.Int32::Parse(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc first&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;Second number: &amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::Write(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call string [mscorlib]System.Console::ReadLine()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call int32 [mscorlib]System.Int32::Parse(string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc second&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc first&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc second&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stloc result&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;{0} + {1} = {2}&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc first&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc second&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldloc result&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; box int32&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string, object, object, object)&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The last thing to notice about this example is that I indicated the method will use at most four stack slots. This is to accommodate the four arguments passed to the WriteLine method at the end of the main method.&lt;/p&gt;&lt;p&gt;Read part 3 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/09/227316.aspx"&gt;Defining Types&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;script type="text/javascript"&gt;







&lt;!--
google_ad_client = "pub-2484098146130174";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel = "";
google_color_border = "6699CC";
google_color_bg = "003366";
google_color_link = "FFFFFF";
google_color_text = "AECCEB";
google_color_url = "AECCEB";
//--&gt;&lt;/script&gt;&lt;script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=226300" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Introduction to MSIL – Part 1 – Hello World</title><link>http://weblogs.asp.net/kennykerr/archive/2004/09/07/introduction-to-msil-part-1-hello-world.aspx</link><pubDate>Tue, 07 Sep 2004 05:55:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:226232</guid><dc:creator>KennyKerr</dc:creator><slash:comments>8</slash:comments><comments>http://weblogs.asp.net/kennykerr/archive/2004/09/07/introduction-to-msil-part-1-hello-world.aspx#comments</comments><description>&lt;p&gt;When describing C++/CLI and how it relates to C#, I am often tempted to discuss the Microsoft intermediate language (MSIL) that the Visual C++ and Visual C# compilers generate. The trouble is that most programmers are not familiar with MSIL and programs like ILDASM aren&amp;rsquo;t that helpful to the newbie because the MSIL they display, although painfully correct, is not very readable. For this reason I decided to post a few entries introducing MSIL at a basic level. Since I doubt anybody reading this will actually go and start writing code in MSIL, I will skim over some of the uninteresting details and focus on things like defining types, writing methods, calling instructions and handling exceptions.&lt;/p&gt;&lt;p&gt;Please let me know if you find this helpful.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s start with a simple main (entry point) function that displays a really unique message. Unlike C#, CLI does not have any requirement that a method must belong to a class. The entry point function also does not have to be called main; however I will use this name in this series for simplicity.&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;.method static void main()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .entrypoint&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .maxstack 1&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ldstr &amp;quot;Hello world!&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call void [mscorlib]System.Console::WriteLine(string)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret&lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The main method above is called a method definition since both the signature as well as the body of the method is provided. In contrast, when a method signature is provided without a body it is referred to as a method declaration. Method declarations are typically used as call targets (when a method is being called) whereas a method definition provides the actual implementation for a method.&lt;/p&gt;&lt;p&gt;A method definition begins with the &lt;strong&gt;.method&lt;/strong&gt; directive and can be defined at global scope or within a class. The application entry point must be static, meaning an instance is not required to call the method, and that is indicated by the &lt;strong&gt;static&lt;/strong&gt; keyword. Declaring a global method static seems redundant but the ILASM compiler complains if you omit the &lt;strong&gt;static&lt;/strong&gt; keyword in some cases. Think of &amp;lsquo;void main()&amp;rsquo; as the signature of the method which, as you would expect, indicates that it does not return a value and takes zero arguments. &lt;/p&gt;&lt;p&gt;The &lt;strong&gt;.entrypoint&lt;/strong&gt; directive signals to the runtime that this method is the entry point for the application. Only one method in the application can have this directive.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;.maxstack&lt;/strong&gt; directive indicates how many stack slots the method expects to use. For example, adding two numbers together involves pushing both numbers onto the stack and then calling the &lt;strong&gt;add&lt;/strong&gt; instruction which pops both numbers off the stack and pushes the result onto the stack. In that example you will need two stack slots.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;ldstr&lt;/strong&gt; instruction pushes the string that is passed to the WriteLine method onto the stack. The &lt;strong&gt;call&lt;/strong&gt; instruction invokes the static WriteLine method on the System.Console class from the mscorlib assembly. This is an example of a method declaration. It provides the full signature of the WriteLine method (including the string argument) so that the runtime can determine which overload of the WriteLine method to call.&lt;/p&gt;&lt;p&gt;And finally the &lt;strong&gt;ret&lt;/strong&gt; instruction returns execution to the caller. In the case of the entry point method, this would bring your application to an end.&lt;/p&gt;&lt;p&gt;Read&amp;nbsp;part 2 now: &lt;a href="http://weblogs.asp.net/kennykerr/archive/2004/09/07/226300.aspx"&gt;Using Local Variables&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&amp;copy; 2004 Kenny Kerr&lt;/p&gt;&lt;script type="text/javascript"&gt;





&lt;!--
google_ad_client = "pub-2484098146130174";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel = "";
google_color_border = "6699CC";
google_color_bg = "003366";
google_color_link = "FFFFFF";
google_color_text = "AECCEB";
google_color_url = "AECCEB";
//--&gt;&lt;/script&gt;&lt;script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"&gt;&lt;/script&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=226232" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/kennykerr/archive/tags/Introduction+to+MSIL/default.aspx">Introduction to MSIL</category><category domain="http://weblogs.asp.net/kennykerr/archive/tags/.NET/default.aspx">.NET</category></item></channel></rss>