オペランドから実効アドレスを求める方法(即値・直接・間接など)
アドレス指定方式(アドレッシング)とは、命令のオペランド部に書かれた情報から、実際にアクセスするメモリの番地(実効アドレス)をどう求めるかを決める方法のことです。実効アドレス=CPUが最終的に「ここを読み書きする」と決める番地のことです。
同じ「300」という数がオペランド部に書かれていても、方式が違えば意味がまったく変わります。「値そのものなのか」「番地なのか」「番地が入った番地なのか」など、解釈のルールを切り替えるのがアドレス指定方式です。上の図解で、5つの方式が同じオペランドをどう扱うか比べてみてください。
身近な例で言うと、メモに「3」と書いてあったとき、「3個ください(値)」なのか「3番の棚(番地)」なのか「3番の棚に貼ってある住所の場所(間接)」なのか──読み方の取り決めが必要ですよね。アドレス指定方式は、まさにその取り決めにあたります。
代表的な5つの方式を整理します。それぞれ「オペランド部の数をどう解釈するか」が違います。
| 方式 | オペランドの意味 | 実効アドレスの求め方 |
|---|---|---|
| 即値 | 値そのもの | 番地ではなく値を直接使う(参照なし) |
| 直接 | 参照先の番地 | 実効アドレス = オペランド |
| 間接 | 番地が入った番地 | 実効アドレス = メモリ[オペランド] |
| インデックス(指標) | ベース番地 | 実効アドレス = オペランド + 指標レジスタ |
| 相対 | 基準点からの差 | 実効アドレス = PC + オペランド |
それぞれの特徴を一言でまとめると次のとおりです。
・即値:値が命令の中にある。最速だが固定の定数しか扱えない
・直接:オペランドがそのまま番地。分かりやすいが表せる番地の範囲が限られる
・間接:番地のさらに先を参照(ポインタ)。柔軟だがメモリアクセスが増える
・インデックス:ベース+指標レジスタ。配列の要素アクセスに最適
・相対:PCからの差分で指定。プログラムをどこに置いても動く(位置独立)
身近な例で言うと、即値は「りんご3個」、直接は「3番の棚」、間接は「3番の棚に書いてある住所の場所」、インデックスは「200番地から8つ目」、相対は「今いる場所から12先」と考えると区別しやすくなります。
各アドレス指定方式では、「実際に使いたいデータ」にたどり着くまでのメモリへのアクセス回数(=参照回数)が異なります。参照回数が多いほど時間がかかるため、方式の選択は処理速度に直結します。
参照回数ごとの方式をまとめます。
・0回(即値):オペランドの値をそのまま使う。命令の中に値が書いてあるので、メモリを読みに行く必要がない。最速
・1回(直接・インデックス・相対):求まった番地のメモリを1回読めばデータが手に入る
・2回(間接):まずオペランドが指す番地を読んで「本当の番地」を得て、その番地をまた読む。2段階なので最も遅い
なぜ間接指定を使うのか。遅いのに使う理由があります。間接指定はオペランドを書き換えなくてもアクセス先を変えられるため、プログラムを書き換えずに動的にアドレスを変更したい場面で有効です。ポインタ(=番地を格納した変数)と同じ考え方です。身近な例で言うと、「Aさんの住所は引き出しの中の紙に書いてある」という状況で、引き出しの中の紙を差し替えるだけで届け先が変えられるイメージです。
インデックスと相対は、どちらも「ある基準点にオペランドの値を足して」実効アドレスを求めます。なぜ加算するのかを理解すると、それぞれの使いどころが見えてきます。
インデックスアドレス指定(指標アドレス指定)は、配列(=同じ種類のデータを連続した番地に並べたもの)へのアクセスに最適です。
・オペランドにベース番地(配列の先頭番地)を書き、指標レジスタ(=計算に使う汎用の記憶場所)に何番目の要素か(添え字)を入れる
・ベース + 添え字 = その要素のアドレスが自動で求まる
・ループのたびに指標レジスタを1ずつ増やすだけで配列を順番に走査できる
相対アドレス指定は、PC(プログラムカウンタ=次に実行する命令の番地を保持するレジスタ)を基準にします。
・「今いる場所から何番地先へ飛ぶ」という形で分岐(if文など)のジャンプ先を指定できる
・プログラムをメモリ上のどのアドレスに置いても、PC相対の差は変わらないため正しく動作する(これを位置独立コードと呼ぶ)
身近な例でまとめると、インデックスは「本棚の5列目から3冊目を取る」(基準 + 番号)、相対は「今の場所から2ブロック先の角を曲がる」(現在地 + 差分)という指示に相当します。直接番地を書く方式と比べて、変化に強い柔軟な指定方法です。
実効アドレスとは、CPUが最終的にアクセスするメモリの番地のことです。アドレス指定方式が違うと、同じオペランド「300」からでも求まる実効アドレスが変わります。具体的に計算してみましょう。
前提: オペランド = 300、メモリ[300] = 500、
指標レジスタ = 8、PC = 100
─────────────────────────
直接 : 実効アドレス = 300
間接 : 実効アドレス = メモリ[300] = 500
インデックス: 実効アドレス = 300 + 8 = 308
相対 : 実効アドレス = 100 + 300 = 400
即値 : 実効アドレスなし(値300をそのまま使用)
求め方のポイントを整理します。
・即値:そもそも番地を求めない。オペランドの値そのものを使う(メモリ参照0回)
・直接:オペランドをそのまま実効アドレスとする(メモリ参照1回)
・間接:オペランドが指す場所の中身を読み、それを実効アドレスとする(メモリ参照2回)
・インデックス・相対:オペランドにレジスタ(指標)やPCの値を加算して実効アドレスを求める
それぞれの方式の特徴を整理すると次のとおりです。
・間接指定はメモリを2回読む(最も時間がかかる)
・インデックスは配列アクセス(ベース番地+要素番号)に便利
・相対はプログラムの再配置(どこに置いても動く)に有利
というように、それぞれの「足し算の中身」と「メモリ参照回数」をセットで理解すると区別しやすくなります。