Finishing an Introductory Look at CIL - Loops
(Page 3 of 7 )
Now comes the difficult part of our program. In the C# version of our program, we quickly put together two for loops nested within each other. In CIL, however, this becomes difficult due to one reason: loops don't exist. Instead, we must manually guide the flow of the program though labels and branches. For one final time, let's break from our prime number program example in order to study flow control in CIL. To do this, let's first look at a simple C# program that prints out the numbers one through ten:
using System;
class Count
{
public static void Main(string[] args)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("Number: {0}", i);
}
Console.WriteLine("Done!");
}
}
Let's break down the loop and examine what exactly the program is doing. Yes, it essentially displays the numbers one through ten, but how exactly does it do that? First, an integer variable is defined, which will act as a counter. Then, the value of this counter is checked to see if it has passed ten. If it hasn't, the number is printed. After it's printed, it's incremented, and after that, we check the value again. Then the value is printed, and this same process of checking, printing and incrementing is repeated. So, we can now break it down into a series of steps:
Assign the initial value to i.
Check to see if the value is less than 10. If it is, go to step 3. If it isn't, skip past the loop.
Print out the number.
Increment i and go to step 2.
Our task is to replicate this behavior in CIL using labels. Let's divide the above steps into sections for our program:
Initialization
Condition
Contents
Incrementation
We have now broken down the behavior of the loop into four words. Now we can begin representing this behavior in CIL. Let's first set up the skeleton of our program:
.assembly extern mscorlib {}
.assembly LoopTest {}
.class public LoopTest
{
.method public static void Main(string[] args)
{
.entrypoint
.maxstack 2
.locals init (int32 I)
ret
}
}
Notice how we define the local variable that we will be using as a counter. Now we need to move on to the first step in our list, which is initialization. This is simple. We need to assign the value one to our variable. This is done by pushing the number one onto the stack and then storing the value at the top of the stack (which will be the number, of course):
ldc.i4.1
stloc i
Don't let the short, seemingly meaningless words scare you. The first line simply puts the number on the stack, and the second line takes the value off of the stack and stores it. Yes, it really is necessary here to go through the stack.
The second step is to check the value of our variable. Notice how we need to repeat this step more than once. Because we need to return to this step, we need to give it a label that we can jump to when appropriate:
loop_condition:
That takes care of the label. Now we need to compare the value of our counter to the number ten. To do this, we have to push both values onto the stack. Again, with CIL, we must work through the stack:
ldloc i
ldc.i4 10
The only thing left is to compare them. If the counter is greater than ten, then we have to jump to the end of the loop. Because we're changing location within the method here, we have to use another label. We'll define this label at the end of everything, but here is how to jump to it:
bgt loop_done
Notice the term “bgt.” Read this as “branch if greater than.” The whole line can be read as “if the one number is greater than the other number, then branch to the label 'loop_done'.” So, here's what we have for the first step:
loop_condition:
ldloc i
ldc.i4 10
bgt loop_done
Next: Loops Continued >>
More ASP.NET Articles
More By Peyton McCullough