2016-09-18 - In IL: Largest of Three Numbers (If-ElseIf-Else)
In IL
- Part 1 - Introduction
- Part 2 - Variables and Types
- Part 3 - Variables in Visual Basic .NET
- Part 4 - Instructions and the Stack
- Part 5 - Volume of a Cylinder (Operations)
- Part 6 - Branching Instructions
- Part 7 - Largest of Two Numbers (if-else)
- Part 8 - Largest of Three Numbers (If-ElseIf-Else)
- Part 9 - Switch instruction
- Part 10 - Grade Analyser (switch)
- Part 11 - Prize Calculator (switch-2)
- Part 12 - VB Grade Analyser (Select)
- Part 13 - Loop Instructions
- Part 14 - Print the Alphabet (while)
- Part 15 - Print the Alphabet (do while, for)
- Part 16 - Print the Alphabet (Do Until)
- Part 17 - Print the Alphabet (break, continue)
- Part 18 - Array Instructions
- Part 19 - Summing Arrays
- Part 20 - Other Instructions
- Part 21 - Assemblies
- Part 22 - Class Definitions
- Part 23 - C# Classes and Structs
- Part 24 - VB Classes, Modules and Structures
- Part 25 - Field Definitions
- Part 26 - Field Declarations
Last time we looked at a program which used an If statement to determine which of two numbers was the largest. If statements can actually get a lot more complicated. They can be extended with additional else if clauses which allow alternative conditions to be tested. The condition can also contain multiple comparisons combined using logical operators.
Continuing from last time let's look at a program that reports which of three numbers is the largest using if, else if, else statements in Visual basic .NET.
Before we look at the compiled output I want to point out one thing. The If condition uses the AndAlso operator (&& in C#) while the ElseIf uses the And operator (& in C#). We will be able to see the difference between these two operators when we look at the compiled code. So let's do that now.
As expected we have three sets of instructions which print text to the console. There are also three branching instructions used to implement the if-else chain.
Branching instructions are generally of the form Value1 Operation Value2 where Value1 is the second value popped off the stack, Value2 is the first value popped off the stack, and Operation is the condition specified by the branch instruction. Last time we determined Value1 and Value2 by running through the program and determining the values on the stack at the point of the branch instruction. This will become very time consuming as our programs get more and more complicated so I'd like to find an easier way.
The value at the top of the stack will be the last value pushed onto the stack and not removed. The value second from the top of the stack will be the second to last value pushed onto the stack and not removed. This means we can determine Value1 and Value2 by working backwards from the branch instruction and looking at what gets pushed onto the stack.
Looking at the first branch instruction on line 90 we see the first instruction before it loads local variable 1 while the second instruction before it loads local variable 0. This means Value1 is NumberA and Value2 is NumberB. The instruction is ble so the condition is NumberA <= NumberB. Looking at the code this matches up with the first part of the if condition (Remember the compiler likes to inverse branch conditions compared to if conditions). If the condition is true we jump to line 110 which is the start of the ElseIf block.
The second branch instruction will only be encountered if the first condition is false. It is also a ble instruction but this time it compares local variable 0 and local variable 2. So the condition is NumberA <= NumberC which matches up with the second part of the if condition. If the condition is true we again jump to line 110. If the condition is false we execute the If block and print that NumberA is the largest.
If either of those conditions are true we branch to the ElseIf Condition. This time though we have two greater-than compare instructions and an and instruction followed by a brfalse instruction. The process for determining comparison values is the same as branching instructions so the full condition is NumberB > NumberA And NumberB > NumberC which is exactly the ElseIf condition. If the result is false we branch to the Else block otherwise we execute the ElseIf block and print that NumberB is the largest.
Why does the ElseIf condition perform the full comparison while the If condition had two branch instructions? As I mentioned earlier the ElseIf uses And while the If uses AndAlso. The difference between these two operators is that AndAlso is lazy. Since logical and requires all of its arguments to be true in order for the result to be true it's possible to know that the result is false after only checking some of the arguments if one of them turns out to be false. AndAlso uses this fact to skip the other comparison if it determines that the first is false. And on the other hand performs all comparisons.
AndAlso is able to make less comparisons which in some ways makes it more efficient. And always executes all comparisons which is important if some of those comparisons have side effects.
Next time we are going to look at the IL Switch instruction.
Comments: