KEN's .NET

[IL16] 配列を作る 〜 String::Splitメソッドの呼び出し

ホーム > KEN's .NET > [IL16] 配列を作る 〜 String::Splitメソッドの呼び出し

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

1. はじめに

前回は配列の使い方を説明しましたが、 今回はStringクラスのSplitメソッドを使う例を通して、 配列の作成、要素の設定について説明したいと思います。 String::Splitメソッドで文字列を分割するには、引数にChar配列を渡す必要があり、 また、戻り値もString配列を返される、という点で配列の説明にはうってつけだからです。 (.NET Framework2.0からはStringの配列を取るバージョンもありますが、 説明には、Char配列を取るオーバーロードを使用します)

2. 配列命令

今回のサンプルで使用する配列関係の命令の一覧を掲載します。 配列の作成にはnewarr、要素の設定にはstelem(store elementの意)で始まる命令を使います。 stelem〜命令については、今回使用する命令以外にもいくつか抜粋して掲載しました。

表1 配列関係の命令
命令命令書式説明スタック遷移図例外
newarrnewarr etypeetype型の要素の新しい配列を生成する。…, numElems → …, arraySystem.OutOfMemoryException:
要求を満足させるのに十分なメモリがない場合。
System.OverflowException:
numElems < 0 の場合。
stelemstelem typeTok配列arrayのindex番目の要素をtypeTok型のvalueで置き換える。.NET Framework 2.0で追加された。…, array, index, value, → …System.NullReferenceException:
arrayがnullの場合。
System.IndexOutOfRangeException:
インデックスが負、配列サイズ以上の場合。
stelem.i2stelem.i2配列arrayのindex番目の要素をint16のvalueで置き換える。…, array, index, value → …,
stelem.refstelem.ref配列arrayのindex番目の要素をオブジェクト参照valueで置き換える。…, array, index, value → …,
※ stelem〜命令については次の命令の掲載を省略しています。(stelem.i、stelem.i1、stelem.i4、stelem.i8、stelem.r4、stelem.r8)
※ 配列はすべて1次元で、インデックスは0からはじまります

3. String::Splitメソッドを呼び出して文字列を分割しよう

図1(NewArray.il)にサンプルプログラム、図2に実行結果を掲載しました。

図1 String::Splitメソッドを呼び出すサンプルプログラム
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 NewArray {}
.method public static void Main()
{
    .entrypoint
    .maxstack 3
    .locals init(char[] chArr, string[] strArr)

    /* 要素数1のchar配列を作成してローカル変数chArrに保存 */
    ldc.i4.1
    newarr char
    stloc.0

    /* char配列に空白(0x20)をセット */
    ldloc.0
    ldc.i4.0
    ldc.i4.s 0x20
    stelem.i2

    /* 文字列を分割した結果をローカル変数strArrに保存 */
    ldstr "AB CDE FGHIJ"
    ldloc.0
    call instance string[] [mscorlib]System.String::Split(char[])
    stloc.1

    /* 配列strArrの全要素を■で区切って表示 */
    ldstr "{0}■{1}■{2}"
    ldloc.1
    call void [mscorlib]System.Console::WriteLine(string, object[])
    ret
}

AB■CDE■FGHIJ
図2 図1のサンプルの実行結果

ソースを順に追っていきましょう。

  • このプログラムはある文字列を空白文字で分割します。
  • 9〜11行目、要素数をスタックに積んで、newarr命令で配列を作成します。 配列は何度も使いまわすことを前提としますので、ローカル変数への保存が必要にです。 char[]で宣言したchArrに保存します。
  • 14〜17行目、char配列の0番目要素として空白(文字コード0x20)を設定します。 charは2バイトの整数ですので、stelem.i2命令を使用できます。 stelem〜命令を使う前にスタックに「配列、セットする要素番号、セットする値」を積んでおきます。
  • 20〜23行目、空白で区切られた文字列"AB CDE FGHIJ"をSplitメソッドで分割します。 分割結果のstring[]はローカル変数strArrに保存します。 Splitメソッド呼び出しを行う前にはスタックには「文字列のインスタンス、分割文字を詰めたchar[]」を積んでおきます。
  • 25〜28行目、分割した結果のstring[]をコンソールに表示します。 3つの文字列に分割されることがあらかじめわかっているので、 Console::WriteLine(string, object[])メソッドを使って手を抜いています。 要素数がわからない場合は、ldlenで要素数を調べて分岐命令でループ処理を行う必要があります。

4. 学んだこと

  • newarr命令で新規配列を作成する
  • stelem〜命令で配列の要素を置き換えできる

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


ホーム > KEN's .NET > [IL16] 配列を作る 〜 String::Splitメソッドの呼び出し

[e-mail] yone_ken00@hotmail.com