- One high-level construct that we have not yet looked at is the SWITCH
statement, e.g.
char gender;
System.out.print("Enter your gender (M or F): ");
gender= scan.nextLine(System.in).charAt(0);
switch (gender) {
case 'M':
case 'm': System.out.println("You are male");
break;
case 'F':
case 'f': System.out.println("You are female");
break;
default: System.out.println("I don't know what you are!");
}
- This could always be rewritten using consecutive IF ... THEN ... ELSE
constructs, e.g.
if (gender == 'M')
System.out.println("You are male");
else if (gender == 'm')
System.out.println("You are male");
else if (gender == 'F')
System.out.println("You are female");
else if (gender == 'f')
System.out.println("You are female");
else
System.out.println("I don't know what you are!");
and hence could be translated to machine-code as a sequence of different
comparisons and branches.
- But this is quite inefficient, as it requires several tests to determine
to print out the last option.
- An alternative is to use a jump table,
so that each option takes the same number of instructions.
- Let's assume that char gender is stored as an 8-bit ASCII
value; in fact, this means only 7 bits are used in the value.
- Let's also write out the machine code to do all the printing as follows:
M_option: nop # An instruction that does nothing
m_option: print "You are male"
branch always to switch_end
F_option: nop
f_option: print "You are female"
branch always to switch_end
default: print "I don't know what you are!"
switch_end: . . .
- Now consider, in the program's data section, an array of 128 words
which hold instruction addresses.
- Most of these hold the address of the instruction at the default
label.
jump_table: .word default, default, default, default, default, ...
but at position 77 (ASCII 'M') in the table, the word holds the value
M_option:
default, default, M_option, default, default, ...
- Similarly, at positions 109, 70 and 102 ('m', 'F' and 'f'), we have
m_option, F_option and f_option, respectively.
- Now, before the code to print out all the message, we can have this
sort of machine code:
do the code to get the gender
lb $t1, gender # Load the gender into a register
mul $t1, $t1, 4 # Multiply $t1 by size of word
lw $t2, jump_table($t1) # Get the instruction address at index position
# $t1 from the jump_table array, store in $t2
jr $t2 # Jump to the instruction at the address in $t2
- If the user enters an 'M', this is treated as ASCII 77.
- We load the word at index position 77 from the jump_table, which
holds the address of the nop instruction at the M_option
label.
- The CPU then performs jr $t2, which is a register indirect
jump: PC <- value in $t2.
- The next instruction performed is the nop, and any code between
the jr and the nop is skipped.
- What have we done? We have traded off a large amount of data (128
jump addresses) for a number of consecutive comparisons and possible
branches.
- Regardless of the character entered by the user, the jump to the matching
instruction takes the same amount of time.
- Also note the "branch always" at the end of each option in the
machine code.
- Can you see that this is equivalent to the break; command
in Java and C?
- This explains why we have to put break; in: it made writing
the early C compilers easier.
- Unfortunately, we are now stuck with having to write break;
all the time.