ベースアドレスにインデックスレジスタの値を加えて実効アドレスを求める方式
インデックスアドレス指定(指標アドレス指定)とは、命令のオペランドが示すベースアドレスに、インデックスレジスタ(=番号を入れておく専用レジスタ)の値を足して実効アドレスを求める方式です。式で書くと 実効アドレス = ベース + インデックスレジスタ値 となります。
身近な例で言うと、「マンションの部屋番号」に似ています。「3階の先頭の部屋(ベース)から数えて2つ隣(インデックス)」と言えば、ベースを変えずに数だけ変えて隣の部屋を次々と指せます。先頭の位置(ベース)と、そこからのズレ(インデックス)に分けて考えるのがコツです。
上のツールでベースとインデックスのスライダーをそれぞれ動かすと、2つの値を足したオレンジの実効アドレスがメモリ上を移動する様子が分かります。インデックスだけ増やすと、配列の a[0], a[1], a[2]… を順にたどれることに注目してください。
この方式では、アドレスを「動かない部分」と「動く部分」の2つに分けて管理します。命令に書かれたベースアドレスは固定の起点、インデックスレジスタの値は実行中に増減させるズレ(変位)です。
実効アドレス = ベース + インデックスレジスタ値
処理の流れは次のとおりです。
・ベースを読む:命令のオペランドから起点アドレスを取得
・インデックスを読む:インデックスレジスタの現在値を取得
・加算する:2つを足して実効アドレスを計算しメモリへアクセス
嬉しいポイント: 命令そのものは変えずに、インデックスレジスタの値を1ずつ増やすだけで次の場所、また次の場所…とアクセス先を移動できます。これがループ処理と非常に相性がよく、後述の配列アクセスで威力を発揮します。
インデックスアドレス指定が最も活躍するのが配列(=同じ種類のデータを連続して並べたもの)へのアクセスです。配列の先頭アドレスをベースに、何番目の要素かをインデックスにすれば、a[i] を簡単に指せます。
厳密には、1要素が複数バイトを占める場合は要素サイズを掛けます。
a[i] のアドレス = ベース + i × 要素サイズ
例) ベース=100, 要素サイズ=4 のとき
a[0] → 100 + 0×4 = 100
a[1] → 100 + 1×4 = 104
a[2] → 100 + 2×4 = 108
ループでの使われ方をまとめると次のようになります。
・初期化:インデックスレジスタを 0 にする(先頭要素を指す)
・処理:ベース + インデックスで要素を読み書き
・更新:インデックスを +1 して次の要素へ。これを末尾まで繰り返す
整理のポイント: 「ベースは固定・インデックスで配列をたどる」という役割分担を押さえておきましょう。ベースアドレス指定(ベースレジスタ+変位)と名前が似ていますが、動かす側がインデックスレジスタなのがインデックス指定という違いで区別できます。