レジスタ (コンピュータ)
出典: フリー百科事典『ウィキペディア(Wikipedia)』
レジスタ(register)はコンピュータのプロセッサなどが内蔵する記憶回路で、制御装置や演算装置や実行ユニットに直結した、操作に要する速度が最速の、比較的少量のものを指す。
目次 |
概説
一般に、論理回路において、フリップフロップなどにより状態を保持する装置をレジスタと呼ぶ。コンピュータにおいては、プロセッサが内蔵しているそれを指す。プロセッサには、プログラムが読み書きできるレジスタ以外に、プロセッサ自身が動作するためのレジスタがあり、内部レジスタなどと呼ばれる。
論理回路において使われるレジスタという用語としては、たとえばレジスタ転送レベルなどがある。
プロセッサ内部のレジスタは、計算結果を一時的に保持したり、RAMやROMなどのメインメモリを読み書きする際のアドレスを保持したり、プロセッサや周辺機器の動作状態を保持・変更したりする。プロセッサの動作とは、極端にいえば、プログラムコードに従ってメインメモリとレジスタの間でデータを移送することだと表現できる。
プロセッサ内部にはたいてい数個から数十個のレジスタがあり、これらの回路はバス回路や演算回路などと密接に結びついているため、高速に動作する。
プロセッサの処理能力について述べる際に、よく「○○ビットプロセッサ(あるいは○○ビットCPU、○○ビットDSPなど)」という表現が用いられるが、このビット数はプロセッサ内部の各レジスタの構成ビット数を指す。レジスタの種類によって、同じプロセッサの中に入っているレジスタでもビット長がまちまちであることがあるが、たいていの場合、演算結果を保持するアキュムレータのビット数がそのプロセッサの処理ビット数であると考える。
多くのプロセッサは、メインメモリとのデータのやり取りに用いるデータバスのビット数と、前述のアキュムレータのビット数とは同じであるが、いくつかのCPUはこれらのビット数が異なる。その場合、データバスのビット数を「外部ビット数」、アキュムレータのビット数を「内部ビット数」と表現する。例えば、モトローラ社のCPU MC68000はデータバスが16ビット、アキュムレータが32ビットだったので、「内部32ビット・外部16ビットCPU」と表現された。
プロセッサの内部にどのようなレジスタがあるかということは、そのプロセッサの構造(アーキテクチャ)を示す最も重要な点である。
レジスタの種類
プロセッサ内部のレジスタには、用途に応じていくつかの種類がある。
通常、レジスタには、マニュアルなどで使われる英字1~3文字程度の略称がある。
専用レジスタ
特定の目的を持つレジスタ。
アキュムレータ
詳細は「アキュムレータ (コンピュータ)」を参照
演算結果を置いたり、データを一時的に記憶するレジスタである。アキュムレータ(accumulator) はあらゆるプロセッサにある。アキュムレータには足し算、引き算などの基本的な演算を行なう回路が付属しており、アキュムレータのデータとデータバス上のデータを演算した結果をアキュムレータに保存することができるようになっている。また、データバスからデータを取り込んだり、データバスにデータを出したりすることができるようになっている。データレジスタと呼ぶこともある。
A, ACCと略すことが多い。
アドレスレジスタ
メモリをアクセスする場合のアドレスを指定するときに用いるレジスタ。この内容をアドレスバスに出す事により、メインメモリからデータを読み出す。また、プロセッサによっては、アドレスを計算するための演算回路が付属しており、実効アドレスの計算を行なうことができるようになっていることもある。
インデックスレジスタ
アドレスレジスタの一種であるが、アドレス計算用の加算回路がついており、メインメモリのアドレスのオフセットを格納するレジスタである。配列データにアクセスするコードが簡単に記述できる。ベースレジスタ、ベースポインタと呼ばれる事もある。
IX,BPなどと略すことが多い。
スタックポインタ
これもアドレスレジスタの一種であるが、プロセッサの動作状態(すなわち内部レジスタの値)を一時保存する場所のアドレスを保持する目的に用いられる場合、スタックポインタと呼ばれる。スタックポインタは、レジスタの内容をデータバスに送出した後に自動的に値が増加または減少する(次の保存場所を指し示す)ようになっている事が多い。また、逆に自動的に値を減少または増加させてからデータバスの内容をレジスタに取り込む機能もついている。これらの動作は、「ポストインクリメント」「ポストデクリメント」「プリデクリメント」「プリインクリメント」と呼ばれる。
SPと略すことが多い。
ページレジスタ、セグメントレジスタ
メモリのアドレス範囲を示すレジスタ。汎用レジスタの設計にすると、アドレスレジスタのビット長は必然的にプロセッサの処理ビット数になってしまうが、8ビット、16ビットといった少ないビット数のプロセッサの場合、これではアドレス空間が足りなくなってしまう事が多い。例えば16ビットプロセッサではアドレス指定も16ビット = 64キロバイトまでしかできない事になってしまうが、これは近年のアプリケーションには小さすぎる。このような場合、アドレスレジスタの上位に数ビットから十数ビットを補ってアドレス空間を広げるという事が行なわれる。この上位ビットを保持するレジスタがページレジスタである。セグメントレジスタの場合、その内容を左に数ビットずらしたものとアドレスレジスタの値を足したものが実効アドレスになる。このようにする事により、メモリ空間内で連続的に使用する事のできない部分をなくす事ができる。
セグメントレジスタを持つプロセッサで最も有名なものは、インテルの8086とその後継CPUである。
プログラムカウンタ
次に実行するべき命令が格納されているメインメモリ上のアドレスを指し示すレジスタ。命令の読み込みを行なう際にはその内容がアドレスバス上に出力され、また命令を読み込む度に読み取った命令の分だけ値が増加するようになっている。分岐命令は、このプログラムカウンタに値を代入することで実現される。さらに、スタックポインタと組み合わせ、プログラムカウンタの内容をスタックに一時保存した後に新たな値を代入すると、サブルーチンの呼出しを実現する事になる。また、スタックから値を取り出してプログラムカウンタに代入すると、サブルーチンから呼出し元に制御を復帰させる事になる。
PCと略すことが多い。また、インストラクションポインタ(IP)、逐次制御カウンタ(Sequential Control Counter; SCC)と称される場合もある。
ステータスレジスタ
詳細は「ステータスレジスタ」を参照
演算結果によって生じた「桁あふれ」やアキュムレータが0であることの状態、あるいは各種のプロセッサの状態を保持するレジスタである。基本的には、ステータスレジスタは読み出し専用である。しかし、読み出しの時にはステータスレジスタとして働き、書き込みの時には後述するコントロールレジスタとして働くようになっていることも多い。
コントロールレジスタ
「ステータスレジスタ」も参照
ステータスレジスタで読み出される各種フラグをリセット(解除)したり、プロセッサを特殊な動作状態にする(動作速度を落として低消費電力状態にするなど)ことを指示するレジスタ。基本的には、コントロールレジスタは書き込み専用であるが、前述のステータスレジスタと共用になっている事も多い。
ゼロレジスタ
何を書き込んでもその結果は反映されず、読み出すと必ず全ビットがゼロである、というレジスタを持つプロセッサがある。一見意味がないようであるが、命令セットを単純化したために、計算結果がある命令は全てその書き込み先を指定しなければならないが、結果が必要ない場合の書き込み先として指定するであるとか、アドレッシングにおいて必ずオフセットを指定しなければならないが、オフセットは必要ない場合、などのために使われる。
汎用レジスタ(ジェネラルレジスタ)
特定の目的を持たず、命令により各種機能を果たすレジスタ。特に、アキュムレータとアドレスレジスタを兼ね備えたレジスタ。
データの計算をする回路とアドレスの計算をする回路を一緒にできる上、命令の種類を減らす事ができるため、ほとんどのプロセッサは汎用レジスタを持っている。また、汎用レジスタを複数個用意しておけば、プログラミングの自由度が格段に増し、特にコンパイラが実行効率の良いオブジェクトコードを生成しやすくなる。RISC系プロセッサでは全ての汎用レジスタが同等の機能を有している事が多い。そのような設計を「レジスタの直交性が高い」と表現する事がある。なお、プロセッサの設計においては、計算対象の指定方法がほぼ全ての命令で同じである(オペランドのアドレッシングが命令に依存しない)ことを「命令の直交性が高い」などと表現する事があるが、これはレジスタの直交性とは異なる概念である。
特殊なアーキテクチャ
レジスタセット
レジスタの値は、プロセッサの内部状態そのものである。つまり、レジスタの値をそっくりそのままどこかに退避させ、後にそれをそっくり元に戻せば、プロセッサの動作を一時中断し、他の作業をさせ、中断前の状態に戻すことができる。
割り込み処理による高速応答性を要求されるアプリケーションを作る場合や、時分割などによる擬似的なマルチタスクを実現する時には、この動作はきわめて頻繁に行なわれる。この、プロセッサの動作状態をそっくり保存して他の動作状態に入れ替えるという動作は、コンテキストスイッチと呼ばれる。
一般には、コンテキストスイッチはスタックを用いてレジスタの内容を外部のメインメモリの一定領域上に一時保存することで実現されている。しかし、コンテキストスイッチを高速化するために、主要なレジスタのコピーを保持する別のレジスタ群をプロセッサ内部に用意しておき、それを用いてコンテキストスイッチを行なう設計になっているプロセッサもある。つまり、プロセッサ内部のハードウェアにより、一瞬にしてアクセスするレジスタを切り替えられる。このようなレジスタ群を「レジスタセット」と呼ぶ。また、切り替えるレジスタ群が1セットしかない場合、それらのレジスタは「シャドーレジスタ」または「裏レジスタ」と呼ばれる。
レジスタセットを用いたコンテキストスイッチは、処理速度を飛躍的に上げられる画期的な手法だが、致命的な問題点がある。レジスタを構成する回路は複雑で、プロセッサ上に多数実装するのが難しい。このため、コンテキストスイッチをするタスクの数が多くなるとレジスタセット内に収まらなくなり、役に立たなくなる。
このため、この手法はあまり複雑な処理をしない、小規模な組み込みシステムで用いられるだけで、一般的なOSでは用いられていない。
レジスタセットを持ったプロセッサで最も有名なものは、ザイログ社のCPU Z80であろう。ただし、セットの数は2つだけであり、一般には裏レジスタと呼ばれている。
ビットの拡張
ソフトウェア資産の有効活用を目的として、16ビットプロセッサの命令セットをそのまま動作できる32ビットプロセッサなどがしばしば開発される。
この場合、プロセッサ内部のレジスタのビット長は大きく(たいていの場合2倍に)なっているのだが、互換性を保つために古いCPUの命令コードで動作する場合には下位のビットしか用いない。
インテル社の8086系列のCPUは、このように拡張してきた経緯を持つ代表的なプロセッサである。8086CPUが誕生する前のインテルの8ビットCPU、8080では汎用レジスタを“a”, “b”, “c”…と名付けていた。これを拡張した8086の汎用レジスタは“ax”, “bx”, “cx”…となった。(xはextendの略)ところが、80386で32ビット化したため、レジスタの名前は“eax”, “ebx”", “ecx”…となった。(eもextendの略)さらに、AMD社がAMD64で64ビットに拡張した時には、レジスタ名は“rax”, “rbx”, “rcx”…とになった。
レジスタと高級言語
レジスタ変数
C言語など、いわゆる高級言語でソフトを記述するとき、計算途中のデータを格納しておく領域は変数と呼ばれる。一般には、コンパイラによって変数にはメインメモリの一領域が割り当てられる。すなわち、「変数の値を読んで計算し、結果を変数に代入する」というコードは、機械語では次のような一連のコードに展開される。
- メモリから値をアキュムレータに取り込む。
- アキュムレータのデータを計算しアキュムレータに入れる
- 計算結果を保持したアキュムレータの内容をメモリに書き出す。
しかし、その変数の値をさらに何度も何度も使って計算を繰り返してゆくようなプログラムの場合、いちいちメモリの読み書きを行なっているのは非常に効率が悪い事になる。
このような時には、レジスタの内容をメモリに書き出す事無く、どんどん使い回すということが行なわれる。特に、近年のプロセッサはアキュムレータとして使えるレジスタの数が多いため、この手法は処理の高速化に非常に役に立つ。
このように、メインメモリ中ではなく、プロセッサ内のレジスタ上に値が格納される変数の事を「レジスタ変数」と呼ぶ。
近年の高性能なコンパイラは、プログラムの構造を深く解析して、どの変数をレジスタ変数にすれば処理効率があがるかを自動的に判断してくれる。このため、プログラムを書く人がレジスタ変数を気にする事はほとんどない。
しかし、コンパイラ最適化がなかった時代には、プログラマが明示的に「この変数をレジスタ変数にせよ」と指示していた。C言語にはこの指示のためのキーワード“register”が用意されている。
サブルーチンの引数
サブルーチンを用いたプログラム(世の中のほとんどのプログラムがそうである)では、サブルーチン呼出し時に計算パラメータを与える事が多い。また、サブルーチンが計算結果を元のルーチンに渡すという事も多く行なわれる。サブルーチンに与えるパラメータを引数、サブルーチンから受け取る計算結果を戻り値と呼ぶが、これらをやりとりするには、一般にはメインメモリ上の一定の領域が用いられる。つまり、呼出し元のルーチンは引数をメインメモリ上の決められた場所に書き込んでからサブルーチンに制御を移す。サブルーチンはその決められた場所のデータを読み取って動作を進める、といった具合である。
一般的なプログラムでサブルーチンの呼出しはきわめて多いため、引数や戻り値の引き渡しの高速化はプログラム全体の動作の高速化にたいへん役立つ。
このためには、メインメモリのアクセスを割愛するために引数や戻り値はレジスタに格納して受け渡すことが望ましい。ただし、プロセッサによってレジスタの数は限られているため、引数の個数が大量になるとこの手法は使えない。
近年のプロセッサはこの目的のために多数のアキュムレータを内蔵しているものが多い。また、一部のRISC型プロセッサでは、もっぱら引数の引き渡しに用いる目的の、スタック動作を内蔵した多数のレジスタ群を用意している。このレジスタ群はレジスタ・ウィンドウと呼ばれる。
ペリフェラルデバイスのレジスタ
ペリフェラルデバイスのレジスタは、ペリフェラル(プログラマブル・カウンタや割り込み制御、シリアル通信ポートなどのハードウェア)の動作を設定したり、動作状況を読み出したりするためのレジスタである。これらのレジスタは上記のプロセッサ内のレジスタとは異なり、プロセッサからアクセスできるアドレス空間の一部に配置される。プロセッサの種類によってはメモリ空間とは別にI/O空間というアドレス空間が存在し、レジスタはここに配置される。I/O空間を持たないプロセッサの場合はメモリ空間にレジスタを配置して利用し、このことをメモリマップドI/Oと言う。レジスタの各ビットの動作や配置はペリフェラルデバイス毎に異なり、ハードウェアの動作をよく理解して操作する必要がある。
組み込み機器用のマイクロコントローラの場合、プロセッサだけでなく多数のペリフェラルデバイスも同一のチップ内に納められており、多くのレジスタがマイクロコントローラ内に存在する。





