KEN's .NET

[IL7] ローカル変数を使ってみる

ホーム > KEN's .NET > [IL7] ローカル変数を使ってみる

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

1. はじめに

ILプログラミングでは一時変数の役割を担うものとして.NET仮想マシンにスタックを持っていますが、 スタックという構造上、一度取り出した値はその時に使い切られて、同じ値を再利用できません。 この点ではVB/C#の変数と異なっています。 ILにもVB/C#での変数(ローカル変数)にあたるものがありますので、 今回はローカル変数を使う方法を紹介します。

2. ローカル変数を扱う命令

スタックからローカル変数へ入れるstloc(store local variable)命令、 ローカル変数からスタックへ入れるldloc(load local variable)命令があります。 これらの命令から派生した命令も含め、詳細は以下の表1に記載しました。

表1 ローカル変数命令一覧
命令命令書式説明スタック遷移図例外
ldlocldloc indxスタックにindx番目のローカル変数をロードします。… → …, valueSystem.VerificationException:localsinitビットがこのメソッドに対してセットされておらず、このメソッドを含むアセンブリにSystem.Security.Permissions.
SecurityPermission.SkipVerificationが与えられていない場合。
ldloc.0ldloc.0スタックに0番目のローカル変数をロードします。… → …, value
ldloc.1ldloc.1スタックに1番目のローカル変数をロードします。… → …, value
ldloc.2ldloc.2スタックに2番目のローカル変数をロードします。… → …, value
ldloc.3ldloc.3スタックに3番目のローカル変数をロードします。… → …, value
ldloc.sldloc.s indxldlocの短形式。… → …, value
stlocstloc indxスタックからindx番目のローカル変数へ値を取り出す。…, value → …なし
stloc.0stloc.0スタックから0番目のローカル変数へ値を取り出す。…, value → …なし
stloc.1stloc.1スタックから1番目のローカル変数へ値を取り出す。…, value → …なし
stloc.2stloc.2スタックから2番目のローカル変数へ値を取り出す。…, value → …なし
stloc.3stloc.3スタックから3番目のローカル変数へ値を取り出す。…, value → …なし
stloc.sstloc.s indxstlocの短形式。…, value → …なし
※他にもldloca/ldloca.sというローカル変数のアドレスをロードする命令もありますが、ここでは扱いません。

3. ローカル変数を使ってみよう

ローカル変数を使う手順は、おおまかに以下のようになります。

  1. .localsディレクティブでローカル変数を宣言する
  2. stloc系命令でスタックの内容をローカル変数へ入れる
  3. ldloc系命令でローカル変数の内容をスタックにロードする(ロードをしても変数に保存した内容は保持される)
図1のサンプルプログラム(LocalVariable.il)で具体的に説明します。

図1 ローカル変数のサンプルプログラム
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.assembly LocalVariable {}
.method public static void main()
{
    .entrypoint
    .maxstack 1
    .locals init (int32 i, string s)  // int32の変数i、stringのsを定義。それぞれ0、nullで初期化

    ldc.i4 1000
    stloc.0     // 0番目のローカル変数(i)にスタック上の1000を入れる
    ldstr "ローカル変数から読み出した値を表示↓"
    stloc.1     // 1番目のローカル変数(s)にスタック上の文字列を入れる
    ldloc.1     // すぐにこの文字列を使用するので、スタックにロード
    call void [mscorlib]System.Console::WriteLine(string)
    ldloc.0     // ローカル変数(i)からスタックへ値を戻す
    call void [mscorlib]System.Console::WriteLine(int32)
    ldloc s     // 変数名sを使って、先の文字列を再びロード。変数名を使ったアクセスも可
    call void [mscorlib]System.Console::WriteLine(string)
    ldloc i     // 変数名iを使って1000をロード
    call void [mscorlib]System.Console::WriteLine(int32)
    ret
}

ローカル変数から読み出した値を表示↓
1000
ローカル変数から読み出した値を表示↓
1000
図2 ローカル変数のサンプルプログラムの実行結果

ソースコードをポイントを押さえて説明します。

  • 6行目では、iとsを変数宣言しています。.localsディレクティブはローカル変数の宣言を指示します。 .localsに続いてinitを指定するとこのメソッドのすべてのローカル変数は0またはnull(VBではNothingにあたる)に初期化されます。 ()の中で変数を宣言しますが、例えばint32の整数i、jを宣言するといったように同じ型の変数を宣言する場合でも、 int32 i,j のような省略した表記はできません。
  • 変数は宣言した順に0からインデックスが割り振られます。ldloc/stloc命令は基本的にはインデックスにより変数を識別します。
  • 9行目のstloc.0命令の意味はインデックスが0番目のローカル変数、つまり、iに対してスタックから値を入れる、ということです。 ldloc.0/ldloc.1/stloc.1についても考え方は同様です。
  • 16行目の「ldloc s」のように変数名を指定することもできます。

4. 学んだこと

  • .localsディレクティブでローカル変数を宣言する。init付きであれば変数は0またはnullで初期化される
  • 変数は宣言した順に0からインデックスが割り振られる
  • ldloc/stloc命令

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


ホーム > KEN's .NET > [IL7] ローカル変数を使ってみる

[e-mail] yone_ken00@hotmail.com