KEN's .NET

[IL12] さらに分岐! 〜 switch命令

ホーム > KEN's .NET > [IL12] さらに分岐! 〜 switch命令

ここでは.NET Frameworkのアセンブリ言語MSIL(Microsoft Intermediate Language)を使ったプログラミングを紹介します。 読者は.NET プログラミング経験があることを想定しています。

1. はじめに

IL9〜IL11の回でしつこいくらい分岐を扱ってきましたが、分岐のしめくくりとしてswitch命令を紹介します。 VB/C#には分岐を行う構文の中で、ある変数に注目してその変数の値に応じて対応する場所へ分岐する命令があります。 VBではSelect Case文、C#ではswitch文です。VBとC#とでこれらの構文は完全に対応するものではありませんが、 一般的な使い方をする上ではほぼ同じものと考えることができます。 しかし、残念ながらILのswitch命令はこれらの命令に比べると非常に貧弱です。

2. switch命令

switch命令の実行直前にはスタック上に1つ以上の値が置かれた状態にします。 switch命令は引数として、(ラベル0,ラベル1, …, ラベルN-1)のようにラベルの集合を指定します。 スタック上の最上部の値が0ならラベル0へ、1ならラベル1へ、…、N-1ならラベルN-1へといったふうに分岐します。 それ以外なら分岐せずに次の命令へ実行を移します。

表1 switch命令
命令命令書式説明スタック遷移図例外
switchswitch ( t1, t2 … tN )n個の値の一つにジャンプする。スタックの一番上のvalueが0〜n-1以外の値の場合、ジャンプせずに次の命令に移る。…, value → …,なし

2. switch命令を使ってみよう

図1(Switch.il)にサンプルプログラムを掲載しました。、 今回のサンプルでもIL11の回で用意したInputInt32.ilのInputInt32メソッドを利用しています。 (複数ilファイルでのアセンブルになりますので、アセンブル方法はIL11の回をご覧ください。)

このプログラムはコンソールで1つの整数を入力し、 その値が0なら"CASE_0"、1なら"CASE_1"、2なら"CASE_2"、それ以外なら"CASE_ELSE"の文字列を表示します。

図1 switch命令を使った分岐のサンプルプログラム
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.assembly Switch {}
.method public static void Main()
{
    .entrypoint
    .maxstack 1

    ldstr "整数を入力してください。:"
    call int32 InputInt32(string)
    switch (
        CASE_0,
        CASE_1,
        CASE_2)
DEFAULT:
    ldstr "CASE_ELSE"
    call void [mscorlib]System.Console::WriteLine(string)
    br SWITCH_END
CASE_0:
    ldstr "CASE_0"
    call void [mscorlib]System.Console::WriteLine(string)
    br SWITCH_END
CASE_1:
    ldstr "CASE_1"
    call void [mscorlib]System.Console::WriteLine(string)
    br SWITCH_END
CASE_2:
    ldstr "CASE_2"
    call void [mscorlib]System.Console::WriteLine(string)
SWITCH_END:
    ret
}

  • 9行目、コンソールから入力された整数を受けて、switch命令が実行されます。
  • (CASE_0,CASE_1,CASE_2)の部分がswitch命令への引数で、スタック上の値が0〜2のときに各ラベルに分岐します。
  • 13〜15行目は、switch命令で分岐が発生しなかった場合のみ実行されます。 VBでのCase Else、C#でのdefaultにあたります。16行目のbr命令でメソッド最後に分岐し、 他のCASE_Xを実行しないようにしています。VB/C#のCase/caseと同じ動作にしています。
  • 17〜20行目、21〜24行目、25〜28行目はそれぞれ、switch命令実行時のスタック上の値が0、1、2のときに 分岐され実行される箇所です。

命令の仕様を確認するとわかるように、switch命令では、 VB/C#のように分岐条件の対象データに文字列を使用することはできません。 それどころか基本的には0から始まる連続した数値である必要があります。 0から始まらない値を対象にしてswitch命令を使う場合には、 事前に引き算して0から始まる値にマッピングするなど一工夫必要です。 連続していない数値の場合はさらに一工夫いりますが、そこまでしてswitchを使うことが、 他の条件分岐命令を使うよりも効果的かどうかは不明です。

3. 学んだこと

  • VBのSelect Case、C#のswitchのような機能で、switch命令がある
  • しかし、分岐条件になる値は0から始まる連続した数値に限定される

A. サンプルダウンロード


ホーム > KEN's .NET > [IL12] さらに分岐! 〜 switch命令

[e-mail] yone_ken00@hotmail.com