UMBC CMSC 211

UMBC | CSEE


Multiway Branching

The Solution in C

In C, we can have a statement like:
i = some expression

if ( i == 1)
{
    some statements0
}
else if ( i == 2 )
{
    some statements1
}
else if( i == 3 )
{
    some statements2
}
else
{
    some statements3
}
  

Yes, it is legal, but not that efficient. You know a better way:

switch (some expression)
{
    case 1:
        some statements0
	break;
    case 2:
        some statements1
	break;
    case 3:
        some statements2
	break;
    default:
        some statements3
        break;
}
  

The Solution in Assembly

The C option is not built into assembly in exactly the same way. OK, every thing in C is built on assembly language, so how do we do it?

For each one of those cases, we need a label to for a JE instruction. If we can assume for the moment that we have an expression that is evaluate, and the results are stored in the AL register, then my example looks like this:

        cmp	AL, 1
	je	L1
	cmp	AL, 2
	je	L2
	cmp	AL, 3
	je	L3
	jmp	LDefault

L1:	some statements0
        jmp	SwitchDone

L2:	some statements1
        jmp	SwitchDone

L3:	some statements2
        jmp	SwitchDone
LDefault:
	some statements3
        jmp	SwitchDone

SwitchDone:

	Whatever comes next
  

So what did we do? First there is a unique label for each case condition. There is also a label for the default condition. Then we compare the register AL with each condition, one at a time, and jump to the label if that condition is met. Finally, if we reach this far, we jump to the default statements.

Inside each case statement in C there is a break. In assembly, we have a jmp to the label that comes after the switch code, or in this case SwitchDone.

So what was the author talking about. There is something called a jump table. A jump table is an array of addresses that will be used with a jmp instruction. We have to have a collection of addresses that we store in an array. Then we need that collection ordered, in such a way, that when we want the first one, we have an indicator that will equal the first array slot (remember it must equal zero, because everything in a computer is zero-based.) Then next one must have an indicator of one, the one after that must have an indicator or two, etc. When that is met, then we can use a jump table. The jump indicatior must be multipled by two, since we are incrementing by two bytes in a word array. Assume that the indicator is in register BX. Now we can have something like:

	jmp  TableLookup
jLabels	DW   L1, L2, L3, Default

TableLookup:
	cmp  BX, 0
	jb   Default
	cmp  BX, 3
	ja   Default 		;Now we have a valid indicator
	shl  BX, 1		;Lazy multiply
        jmp  [jLabels + BX]

L1:	some statements0
	jmp  TableDone

L2:	some statements1
	jmp  TableDone

L3:	some statements2
	jmp  TableDone

Default:
	some statements3

TableDone:
   	 Whatever comes next

  

If you have the situation where you have most of the values in sequence, but one or two are missing, then for those missing ones, you also jump to the Default label.

Also, if you have the situation where you have a range of values that does not start at zero, say 42 to 46, then make the jmp like this:

	jmp [jLabels + BX - 42]
  
Then if BX is 42, 42 - 42 is zero, so it works correctly.


UMBC | CSEE