アドレッシングモード

アドレッシングモード(Addressing Mode)は、CPUの命令セットアーキテクチャ(ISA)の一部を構成する。プロセッサの命令には操作対象をオペランドで指定するものがあり、その指定方法の詳細がアドレッシングモードと呼ばれるものである。したがって、広義のアドレッシングモードにはレジスタを指定する場合も、値が命令のオペランドとして直接与えられている場合も含まれるが、狭義のアドレッシングモードはオペランドとして使用すべきメモリ領域を指定するものとみなされる。
プログラミングの観点から言えば、アドレッシングモードが重視されるのはコンパイラ開発やアセンブリ言語でプログラミングする場合である。

どれだけのアドレッシングモードがあるか

コンピュータ・アーキテクチャが異なれば、それぞれに独自のアドレッシングモードがある。複雑なアドレッシングモードを廃し、数個の単純なアドレッシングモードだけにすると、使用する命令数が増え、レジスタも多く必要になるが、アドレッシングモードを単純化することで、CPUの命令パイプラインの設計が容易になるという利点があると言われている。
RISCでは一般にアドレッシングモードが少なく単純だが、DECのVAXなどのCISCでは1ダース以上のアドレッシングモードを備え、その一部は非常に複雑である。IBM System/360 は3種類のアドレッシングモードしか持たなかったが、System/390ではいくつか追加されている。
アドレッシングモードが少ない場合（例えばRISCや IBM System/390）、命令コード側にオペランドの意味を規定する情報が含まれている。しかしアドレッシングモードが豊富なアーキテクチャでは命令フォーマット内に命令コードとは別にアドレッシングモードを指定するフィールドが存在する。DEC VAX はほとんど全ての命令で複数のメモリオペランドを指定でき、オペランド指定フィールドの先頭数ビットで、そのオペランドのアドレッシングモードを指定するようになっている。アドレッシングモードを指定するビット列をオペコードから分離した命令セットは「直交性が高い」と言われる。
豊富なアドレッシングモードを持つコンピュータであっても、実際のプログラムを調べてみると、90%は単純なアドレッシングモードで済んでいる。これは高水準言語のコンパイラが生成したコードを調査した結果であり、コンパイラ自体の限界を反映したものということもできる。

既に使われなくなったアドレッシングモード

以下に挙げるのは、1980年代ごろまで使われていたアドレッシングモードであるが、現在では使われていない。これが全てを網羅しているものではなく、時に応じて様々なアドレッシングモードが使われてきた。例えば、直接アドレス値に複数のインデックスレジスタの論理和を加算するなどといったものもあった。

初期のコンピュータ

EDSACなどは、主記憶装置の容量が小さいため、アドレス指定は全て直接であった（命令内にアドレスが書かれていた）。しかし、これでは配列の各要素に同じ演算をするようなループをコーディングすることが困難である。というのは、ループにしたとき毎回違う配列要素にアクセスするには命令を書き換えなければならなかったからである（実際、命令を書き換えてループさせていた）。これに対してManchester Mark Iではインデックスレジスタを実装して命令を書き換えなくても済むようにした。
別の解決方法として、次の命令のオペランドを修飾する命令を持ったマシンも存在した。エリオット・ブラザーズの Elliott 503 や Elliott 803、アポロ誘導コンピュータなどは絶対アドレッシングしか持たず、インデックスレジスタも持っていなかった。従って間接アドレッシングによる分岐やレジスタを使った分岐は命令セットに存在しない。その代わりとして「指定したメモリワードの内容を次の命令に加える」という命令がある。例えば次の命令が JUMP 0 だった場合、メモリから読み込んだ値が 20 だったとすると JUMP 20 に書き換えられる。これによってインデックス付きの分岐命令と同等の効果を得る。なお、命令は実行時に更新されるのであって、メモリ上の内容は書き換えられない。したがってこれは自己書き換えコードではない。指定したメモリ位置の内容が大きい場合、オペランド（アドレス）だけでなく命令コードまで変更することができる。

多重メモリ間接

何らかの実効アドレスがメモリ上の領域を示していて、そこに別のメモリ領域のアドレスが格納されていて、さらにその先にまでたどってメモリの内容をとってくるような場合を多重メモリ間接という。例えばMC68020などは二重メモリ間接までは実装していた。その際、いったんメモリアクセスして取ってきたアドレス値にさらにインデックスレジスタやディスプレースメントを加算して第二の実行アドレスを計算するモードが存在した。
TRONCHIPでは「多段間接モード」を持つ。1段の間接参照操作の中で、インデックスレジスタのスケーリングと加算、オフセットの加算、メモリの間接参照、の3動作を行い、これを任意の段数反復することが可能であった。
DEC の PDP-10では、アドレスが18ビット幅でワード長が36ビットであるため、ワード内にポインタとフラグを含めることができる。メモリに格納するワードの中の、間接メモリ参照を許可するフラグを設定することによって自動的に多重メモリ間接が可能であった。この場合、ポインタがループを形成していると永久にループをたどり続けるため、注意が必要である。一般にワード長がアドレス長より長い場合、このような多重間接が可能で、他にも IBM 1620、Data General Nova などがある。Novaの多重メモリ間接から間接スレッデッドコードの発想が生まれた。

メモリマップド・レジスタ

DEC PDP-10 などは、レジスタがメモリの先頭アドレス部分（0番地付近）を使って実現されていた（つまり、レジスタがメモリ空間にマップされていた）。これを活用すると、小さなループを構成する命令（機械語）をレジスタに並べておくと、高速にループを実行することができた。
後のPDP-11シリーズではレジスタを入出力エリアにマッピングしていたが、これは遠隔診断を意図したものである。

自動インクリメント付きメモリ間接

PDP-8などの初期のミニコンピュータでは、特別なメモリアドレスがいくつかあり、そこにメモリ間接でアクセスすると、メモリの内容をアクセス後に自動インクリメントしたり、自動デクリメントしたりする（アドレスによって異なる）。これを使うとレジスタを使わずにループを実行することが容易になる。

ゼロページとダイレクトページ

Data General Nova、MC6800ファミリ、MOS 6502 ファミリなどは内蔵レジスタ数が非常に少ないアーキテクチャである。そのため、多くの算術命令をメモリ上の値に対して行う。普通にアドレスを指定すると16ビット必要とし、コードの中でアドレス指定に要するメモリ量がかなり大きくなる。
そのため、プロセッサ設計者は「ゼロページ」アドレッシングと呼ばれる緩和手段を実装した。メモリ空間の先頭256バイト（$0000 - $00FF; これがすなわちページ "0" である）を1バイトで指定できるアドレッシングモードを用意したのである。インデックス付きもある。これによって命令長が1バイト短縮され、クロックサイクルも1サイクル短縮される。結果としてゼロページはレジスタファイルのような使い方をされた。
6502を発展させた WDC 65816 や MOS 65CE02、MC6809などでゼロページ・アドレッシングが強化され、「ダイレクトページ」アドレッシングとなった。これは、256バイトのゼロページの開始アドレスを専用レジスタで自由に設定できるようにしたもので、それによって複数のソフトウェアがダイレクトページを切り換えて使えるようになった。

ワードを任意サイズのバイトで分けて指定

PDP-10は36ビットのワード長で、1ビットから36ビットまでの任意サイズのバイト単位でメモリを指定する特殊なアドレッシングモードを持つ。18ビットのワードアドレス、ワード内のビット位置、バイトのサイズを指定する1ワードの記述子を使用する。
この記述子を使ってバイト単位でロード・ストアする命令が存在し、記述子が次のバイトを指すようインクリメントする（バイトはワード境界をまたがない）。DECのソフトウェアでは1バイトを7ビット（ASCII）とし、1ワードを5バイトと未使用の1ビットにする記述子を使うことが多かった。C言語では、int 型が char 型の整数倍であるという前提で malloc 関数が成り立っていたため、1バイトを9ビットとし、1ワードを4バイトちょうどにする必要があった。実際何倍なのかはコンパイル時の演算子であるsizeofで決まる。