SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Microsoft .NET ILアセンブラ入門

.NET Framework SDK付属のアセンブラを使った開発

  • X ポスト
  • このエントリーをはてなブックマークに追加

制御

 次に、簡単な制御方法について説明します。プログラムの流れ制御は、高水準言語のような構造的なものではないので、命令単位に自由にジャンプできます。いわゆるif文のような分岐も可能ですし、goto文のような無条件ジャンプも可能です。

 無条件ジャンプは、強制的に実行するコードを指定の位置に移動するbr命令を使います。

br命令
br target

 targetには、移動先のコードのアドレスを指定します。実際には、メソッド内のコードのオフセットを表す4バイトの整数が保存されますが、アセンブリ言語内では命令に名前を付けて、識別子で指定できます。命令には、コードラベルと呼ばれる名前を付けることができます。コードラベルは次のように指定します。

コードラベル
Id:

 このコードラベルの直後が、移動先の対象命令となります。コードラベルのIdに指定した識別子を、br命令のtargetに設定することで、強制的にラベルの命令まで移動します。この命令を使うことで、同一メソッド内の任意の命令にジャンプできます。

Sample05
.assembly extern mscorlib { }
.assembly test { }

.method static void Main() cil managed {
    .entrypoint

    ldstr "さぁ、始まるザマスよ"
    call void [mscorlib]System.Console::WriteLine(string)

    br target

    ldstr "行くでガンス"
    call void [mscorlib]System.Console::WriteLine(string)
    
target:
    ldstr "ふんがー"
    call void [mscorlib]System.Console::WriteLine(string)
    ret
}
実行結果
さぁ、始まるザマスよ
ふんがー

 Sample05は、メソッドの途中でbr命令を使って、途中のいくつかの命令を省略するプログラムです。コード内では3回WriteLine()メソッドの呼び出しが行われていますが、中間の呼び出しは実行されません。br命令が実行された時点で、制御はtargetラベルのldstrに移動します。

 条件分岐には、計算と同じようにスタックに読み込まれている値が使われます。分岐の方法は、値が0以外のtrueを表す場合に実行されるbrtrue命令と、値が0、すなわちfalseやnullの場合に実行されるbrfalse命令があります。

brtrue命令
brtrue target

 書式はbr命令と同じです。この命令を実行すると、スタックに読み込まれている値がポップされ、その値が0以外であればtargetに分岐します。nullでなければ分岐するという意味の別名でbrinst命令も用意されています。brtrueもbrinstもオペコードは同じなので、単純な別名です。どちらを使っても構いませんが、通常は調べる対象が値型であればbrtrue、参照型であればbrinstを使った方が分かりやすいでしょう。

 値が0であれば分岐するbrfalse命令も、仕組みは同じです。

brfalse命令
brfalse target

 やはり、スタックに読み込まれている値がポップされ、その値が0であればtargetに分岐します。同一の意味をもつ別名の命令でbrnullおよびbrzeroも用意されていますが、やはりオペコードは同じです。

 brtrueまたはbrfalseいずれかの命令を使うことで、高水準言語におけるif-else文の処理が実現できます。

Sample06
.assembly extern mscorlib { }
.assembly test { }

.method static void Main() cil managed {
    .entrypoint

    ldc.i4.1

    brfalse else

    ldstr "スタックは true です"
    call void [mscorlib]System.Console::WriteLine(string)
    br endif

else:
    ldstr "スタックは false です"
    call void [mscorlib]System.Console::WriteLine(string)

endif:    
    ldstr "分岐処理を終了します"
    call void [mscorlib]System.Console::WriteLine(string)

    ret
}
実行結果
スタックは true です
分岐処理を終了します

 Sample06は、最初のldc.i4.1命令でスタックに読み込んだ値を使って分岐処理を行い、trueかfalseかを表す文字列を出力します。命令にはbrfalseを使っているので、スタックの値がtrueであればそのまま逐次に実行され、そうでなければelseラベルまでジャンプします。brfalseでジャンプしなかった場合、そのままコードが続けて実行されます。elseラベル以降がそのまま実行されないように、br命令でendifまでジャンプしています。

 ちなみに、.NET Framework SDK付属のC#コンパイラでbool型の変数をif文に与えた場合、変数の値と0をスタックに読み込んだあと、値が等しいかどうかを調べるceq命令を使っています。その後brtrue命令で変数の値が0、すなわちfalseであればelse部分にジャンプし、そうでなければ実行を続けるという流れになっていました。

 本稿では解説していないため割愛しますが、変数を使うことで反復処理も同じ原理で実現できます。変数に繰り返す回数を代入し、変数の値をスタックに読み込んで0かどうかを調べ、0でなければ処理を実行して値をデクリメントします。最後に、処理の冒頭にジャンプすることで、変数の値が0になるまで処理が繰り返されます。

最後に

 さて、本稿ではアセンブリ言語の基本的な構造と命令について説明しました。本稿の内容に加えて、クラスやメソッドなどを宣言するディレクティブを使うことで、他の高水準言語と同じように、構造的にコンポーネントを開発できます。ディレクティブについては割愛しましたが、その多くはVisual BasicやC#の経験があれば、直観的に理解できるものでしょう。ILDASMを使って逆アセンブルしたコードを解析して、コンパイラがどのような中間言語を生成しているのかを調べるのも面白いと思います。

 アセンブリ言語を実践の開発現場で実用することは、生産性や保守性の面で困難かもしれませんが、これを理解することで.NET Frameworkの本質が見えてきます。もし、Visual BasicチームとC#チームが対立し、どうにもプロジェクトがまとまらないときは、アセンブリ言語を叩きこむことで仲良くなるかもしれません。少数派のC++/CLIチームが親の敵のようにマネージテンプレートを使って我が道を突き進んでいる時も、逆アセンブルすることで、どのようなコードが生成されているのか調べられます。

 どちらにしても、アセンブリ言語を理解することで、こういった小回りが利くことは多少なりのメリットになるはずです。さらに、特殊な開発支援ツールや、実行時の型解析、ロジックの生成などにも、CILの知識が必要になります。動的な中間言語の生成は、間もなく登場する予定の動的言語ランタイムや.NET Framework 3.5で追加された式木の基礎にもなっている重要なテクニックです。

 アイデア次第で面白いプログラムが書けるかもしれません。ぜひ試してみてください。

参考

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

赤坂 玲音(アカサカ レオン)

平成13年度「全国高校生・専門学校生プログラミングコンテスト 高校生プログラミングの部」にて最優秀賞を受賞。2005 年度~ Microsoft Most Variable Professional Visual Developer - Visual C++。プログラミング入門サイト WisdomSoft の管理人。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2624 2008/06/26 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング