One relatively unusual quality of tree-based n-way conditionals that makes
them a bit easier to make out while reading disassembled code is the numer-
ous subtractions often performed on a single register. These subtractions are
usually followed by conditional jumps that lead to the specific case blocks (this
layout can be clearly seen in the 501_Or_Below case in Figure A.12). The com-
piler typically starts with the original value passed to the conditional block
and gradually subtracts certain values from it (these are usually the case block
values), constantly checking if the result is zero. This is simply an efficient way
to determine which case block to jump into using the smallest possible code.
Loops
When you think about it, a loop is merely a chunk of conditional code just like
the ones discussed earlier, with the difference that it is repeatedly executed,
usually until the condition is no longer satisfied. Loops typically (but not
always) include a counter of some sort that is used to control the number of
iterations left to go before the loop is terminated. Fundamentally, loops in any
high-level language can be divided into two categories, pretested loops, which
contain logic followed by the loop’s body (that’s the code that will be repeat-
edly executed) and posttested loops, which contain the loop body followed by
the logic.
Let’s take a look at the various types of loops and examine how they are rep-
resented in assembly language,
Pretested Loops
Pretested loops are probably the most popular loop construct, even though
they are slightly less efficient compared to posttested ones. The problem is that
to represent a pretested loop the assembly language code must contain two
jump instructions: a conditional branch instruction in the beginning (that will
terminate the loop when the condition is no longer satisfied) and an uncondi-
tional jump at the end that jumps back to the beginning of the loop. Let’s take a
look at a simple pretested loop and see how it is implemented by the compiler:
c = 0;
while (c < 1000)
{
array[c] = c;
c++;
}
You can easily see that this is a pretested loop, because the loop first checks
that cis lower than 1,000 and then performs the loop’s body. Here is the assem-
bly language code most compilers would generate from the preceding code:
504 Appendix A
21_574817 appa.qxd 3/16/05 8:54 PM Page 504