1. はじめに
ILプログラミングでは一時変数の役割を担うものとして.NET仮想マシンにスタックを持っていますが、
スタックという構造上、一度取り出した値はその時に使い切られて、同じ値を再利用できません。
この点ではVB/C#の変数と異なっています。
ILにもVB/C#での変数(ローカル変数)にあたるものがありますので、
今回はローカル変数を使う方法を紹介します。
2. ローカル変数を扱う命令
スタックからローカル変数へ入れるstloc(store local variable)命令、
ローカル変数からスタックへ入れるldloc(load local variable)命令があります。
これらの命令から派生した命令も含め、詳細は以下の表1に記載しました。
表1 ローカル変数命令一覧
| 命令 | 命令書式 | 説明 | スタック遷移図 | 例外 |
| ldloc | ldloc indx | スタックにindx番目のローカル変数をロードします。 | … → …, value | System.VerificationException:localsinitビットがこのメソッドに対してセットされておらず、このメソッドを含むアセンブリにSystem.Security.Permissions. SecurityPermission.SkipVerificationが与えられていない場合。 |
| ldloc.0 | ldloc.0 | スタックに0番目のローカル変数をロードします。 | … → …, value |
| ldloc.1 | ldloc.1 | スタックに1番目のローカル変数をロードします。 | … → …, value |
| ldloc.2 | ldloc.2 | スタックに2番目のローカル変数をロードします。 | … → …, value |
| ldloc.3 | ldloc.3 | スタックに3番目のローカル変数をロードします。 | … → …, value |
| ldloc.s | ldloc.s indx | ldlocの短形式。 | … → …, value |
| stloc | stloc indx | スタックからindx番目のローカル変数へ値を取り出す。 | …, value → … | なし |
| stloc.0 | stloc.0 | スタックから0番目のローカル変数へ値を取り出す。 | …, value → … | なし |
| stloc.1 | stloc.1 | スタックから1番目のローカル変数へ値を取り出す。 | …, value → … | なし |
| stloc.2 | stloc.2 | スタックから2番目のローカル変数へ値を取り出す。 | …, value → … | なし |
| stloc.3 | stloc.3 | スタックから3番目のローカル変数へ値を取り出す。 | …, value → … | なし |
| stloc.s | stloc.s indx | stlocの短形式。 | …, value → … | なし |
※他にもldloca/ldloca.sというローカル変数のアドレスをロードする命令もありますが、ここでは扱いません。
3. ローカル変数を使ってみよう
ローカル変数を使う手順は、おおまかに以下のようになります。
- .localsディレクティブでローカル変数を宣言する
- stloc系命令でスタックの内容をローカル変数へ入れる
- 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)
ldc.i4 1000
stloc.0
ldstr "ローカル変数から読み出した値を表示↓"
stloc.1
ldloc.1
call void [mscorlib]System.Console::WriteLine(string)
ldloc.0
call void [mscorlib]System.Console::WriteLine(int32)
ldloc s
call void [mscorlib]System.Console::WriteLine(string)
ldloc i
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. サンプルダウンロード
|