the program jump to the default block. To efficiently implement the table
lookup, the compiler subtracts 1 from ByteValueand compares it to 4. If
ByteValueis above 4, the compiler unconditionally jumps to the default
case. Otherwise, the compiler proceeds directly to the unconditional JMPthat
calls the specific conditional block. This JMPis the unique thing about table-
based n-way conditionals, and it really makes it easy to identify them while
reversing. Instead of using an immediate, hard-coded address like pretty
much every other unconditional jump you’ll run into, this type of JMPuses a
dynamically calculated memory address (usually bracketed in the disassem-
bly) to obtain the target address (this is essentially the table lookup operation).
When you look at the code for each conditional block, notice how each of the
conditional cases ends with an unconditional JMPthat jumps back to the code
that follows the switch block. One exception is case #3, which doesn’t termi-
nate with a breakinstruction. This means that when this case is executed, exe-
cution will flow directly into case 4. This works smoothly in the table
implementation because the compiler places the individual cases sequentially
into memory. The code for case number 4 is always positioned right after case
3, so the compiler simply avoids the unconditional JMP.
Tree Implementation
When conditions aren’t right for applying the table implementation for switch
blocks, the compiler implements a binary tree search strategy to reach the
desired item as quickly as possible. Binary tree searches are a common concept
in computer science.
500 Appendix A
VALUE RANGES WITH TABLE-BASED N-WAY CONDITIONALS
Usually when you encounter a switch block that is entirely implemented as a
single jump table, you can safely assume that there were only very small
numeric gaps, if any, between the individual case constants in the source code.
If there had been many large numeric gaps, a table implementation would be
very wasteful, because the table would have to be very large and would contain
large unused regions within it. However, it is sometimes possible for compilers
to create more than one table for a single switch block and to have each table
contain the addresses for one group of closely valued constants. This can be
reasonably efficient assuming that there aren’t too many large gaps between
the individual constants.
21_574817 appa.qxd 3/16/05 8:54 PM Page 500