9.6 'switch/SWITCH' statement

-------------------------------

Syntax:

switch(<expression>){

case <constant>:

<operator>

...

case <constant>:

<operator>

...

...

default:

<operator>

}

The statement 'switch' is used for choosing among several alternate

ways of executing a program. Execution begins by calculating the value of

<expression>. After this control passes to one <statement> of the switch

body. The switch body contains the constructions <constant> case which are

syntactically statement labels. The statement which gets control is the one

whose constant value coincides with the <expression> value of the switch.

The <constant> value must be unique.

Execution of the body of 'switch' begins with the chosen statement and

continues to the end of the body or until some statement does not pass

control beyond the body.

A statement following the keyword 'default' is executed if one of the

constants is equal to <expression>. If 'default' is omitted, none of the

statements in the switch body is executed and control passes to the

statement following 'switch'.

'break' or 'BREAK' are usually used to exit the body of 'switch'.

Example:

switch (i){

case 'A':

WRITE(i);

i++;

BREAK;

case 32:

WRITE('_');

i++;

BREAK;

default:

WRITE('i');

}

There are currently three ways to implement 'switch': two-table,

table, and method of sequential verification.

The table method is fastest, but with a large number of 'case'

statements and a small difference between maximum and minimum values of

'case' it can be even more compact. It has certain drawbacks: in 16-bit

mode register BX is always used, and in 32-bit mode if 'switch' is a

register then its value is destroyed.

In the sequential verification method, a comparison block is found at

the beginning of the body of 'switch' which saves one or two extra jumps.

But the compiler cannot determine which type of jump to used when checking

the values of 'case'. This is the job of the programmer. If the code size

from the start of the body of 'switch' to 'case' is less than 128 bytes, a

short jump can be used. In this event 'CASE' can be used, which results in

the generation of more compact code. The compiler will suggest using

'CASE'. Using 'CASE' when the code is over 128 bytes will produce an error

message.

In the two-table method two tables are created - an input address table

in the body of 'switch' or 'SWITCH' and a table of values of 'case'. The

input value is compared with the value in the second table. If they are the

same then a jump is made by the address in the second table. This method if

the slowest but if there are many values of 'case' (more than 15) it is the

most compact.

If code is being optimized for size, the compiler first calculates the

code size which will be obtained by all the methods and produces the most

compact code. When optimizing for speed, priority is given to the table

method if the table size is not too large.

There is a short form 'SWITCH' used if the code block between the

beginning of the body of 'SWITCH' and 'default' (or the end of the body of

'SWITCH' if there is no 'default') is less than 128 bytes. The compiler

will suggest the use of the short form.

You can specify a range of values for 'case' or 'CASE', which can be

used only the body of 'switch' or 'SWITCH'. The smaller value is given

first, followed by an ellipsis and the larger value. For example:

switch(AX){

case 1...5:

WRITESTR("Range AX from 1 to 5");

BREAK;

};

It used to be necessary to write:

switch(AX){

case 1:

case 2:

case 3:

case 4:

case 5:

WRITESTR("Range AX from 1 to 5");

BREAK;

};

The new format is also more compact and more readable, and will

generate smaller and faster code.