いきなりですが、PDP11のアドレシング・モードの説明のOHPです。PDP−11には八つのアドレアシングモードがあります。すでに、0n、27、37と解説しましたが、今回はもう少し系統的に説明します。いちどに、説明すると少しややこしいかもしれませんが、お付き合いお願いします。
まず、間接モードです。これは、オペランドの指定する場所を、アドレスとして解釈するモードです。オペランドの高位3ビットで、アドレッシングを区別しますが、この一番下位の3ビット目が0を含む場合、すなわち、アドレシング指定が偶数の場合は、直接アドレッシング、奇数の場合(3ビット目が1)が、間接アドレシング・モードです。例えば、オペランドが0n(nは8進数で、0から7のレジスタを指定)の時は、レジスタnの内容が、オペレータの作用対象になります(直接アドレッシング)。1nの場合は、レジスタnの値の指す番地のデータが対象になります。(間接アドレッシング)
命令語の直後にオペランドが続く27、37のアドレッシングも2が直接アドレシング、3が間接アドレシングを表しています。
0nと2nの違いは何かというと、0n、1nの場合は、命令の実行後も、nで表されるレジスタはの内容は不変です。2n、3nの場合は、命令の実行後にレジスタの内容が、原則、2増えます。これは、次々にデータをアクセスする場合に便利です。例えば、配列を逐次処理する場合とか。命令を実行するたびに、レジスターの内容が増加するので、プログラムを短くできますし、プログラムの見通しが良くなります。C言語での
for(i = 1; i <= 10; i++)
{…}
のような感じでプログラムを書けて便利です。
レジスタを自動インクリメント(増やす)するアドレシングがあるならば、自動デクリメント(減らす)アドレシングモードもあるのかと言うと、ございます。これは、4n、5nで指定します。これは次に出てくるスタックというデータ構造の操作に向いています。ここで注意すべきは、2n、3nがデータにアクセスしたあとに増加するのに対して、4n、5nは、データにアクセスする前に、デクリメントするところが違います。
c言語風に書くと
2n, 3n は i++ なのに対して、4n、5n は --i
になります。なんでこんな仕様なのかというと、スタックにつまれたデータを取り扱うのにこの仕様の方が便利なためだと思われます。ちなみに、PDP−11には スタックにレジスタの内容を積むPUSH命令や、スタックからデータを降ろすPOP命令はありません。これらには6番レジスタ(R6)を間接アドレシングで使用します。例えばR0の内容をスタックに積むには、
010056 と書きます。アッセンブラ風に書くと MOV R0, -(SP)
スタックポインタを2減らして、R0のデータを書き込みます。
スタックトップのデータをR0に戻すには
013600 これは アセンプラ風に書くと 、 MOV (SP)+,R0 となります。
このようにして、PUSH、POPなしで、スタック操作が可能になります。
ここまでで、八つのアドレシングモードのうち六つの解説が終わりました。最後のモードは、モードはインデックス・モードの直接モード(6n)と、間接モード(7n)です。これは、指定されたレジスタに命令語の次のアドレスのデータ(x)を加えたものを目的のアドレスにするというモードで、表の操作などに便利です。加えるXは2の補数方式のマイナスの数でも、問題ありません。例えば、二次元の表で、R1に行の先頭の項目の番地があれば、Xに適当な値を入れれば、任意の項目のデータにアクセスできます。R1に、行の先頭データアドレスが入っている時に、 その次の項目のデータを、R0 レジスタに、読み込む命令はアセンブラ風に書くと、
MOV 2(R1),R0
になり、機械語で書くと
016100
00002
になります。
これで、PDP−11の八つのアドレッシング・モードについて、説明しました。八つのレジスターに八つのアドレッシング・モードで、64パターンのアクセス方法が可能です。PDP−11は、豊富なアドレッシング・モードを持っていると良く言われますが 基本のアドレッシング・モードは 4種類に、直接、と間接の2パターンと、8パターンのレジスタ指定の組み合わせですからそんなに複雑ではありません。しかし、これらを使いこなすには、多少の経験が必要になると思います。
次に、サブルーチン・コールについて、見ていきましょう。
例えば、テレタイプに一文字出力するような、何回も繰り返して行う操作は、サブルーチンとして、まとめて、メインプログラムから、呼び出す方が、プログラムがコンパクトになります。また、プログラム全体の見通しもよくなります。大抵のCPUには、サブルーチン呼び出しとサブルーチンからの戻るをサポートする機能が装備されています。PDP−11にもJSR命令(Jump to SubRutine)とRTS(ReTurn from Subrutine)という命令があります。
木村泉先生のOHPでは、サブルーチンコールは 4737 、 戻りには 207の機械語を使うように示しています。他のCPUと同じように使うのであれば、全く問題ありません。しかし、ちょっと変わった使い方もできます。
PDP−11にはサブルーチン・コールする場合、リンケージ・レジスタを指定します。細かいことはどうでもいいという方は、以下は読みとばして下さい
実は、4737、207をそれぞれアセンブラ風に書くと、
JSR PC, @#XXXXX
RTS PC
XXXXXはサブルーチンの先頭番地です。
となります。PCとなっている部分が、リンケージ・レジスタの指定となり、必ず、R0からR7のいづれかを指定しなければなりません。
例えば、
1000: 004137
1002: 003000
1004:…………
1000番地に JSR R1,@#3000
に相当する命令が書かれていたとしましょう。この命令に対して、PDP−11は、次のように動作します。
まず、リンケージ・レジスタR1 の内容を スタックに退避します。次にプログラム・カウンタの内容(戻り番地)1004をR1に移動します。そして3000番地の命令を実行します。
では、サブルーチンから戻る場合は、
3050:000201 RTS R1
という命令があってそのサブルーチンから戻るとします。PDP−11の動作は次のようになります。まず、R1の内容を、プログラムカウンタPC: R7に戻します。 次に、スタックから卸したデータをR1 に戻します。プログラムは、リターン命令の直前のR1レジスタの内容のデータの指す番地から再開します。
リンケージ・レジスタに PC; R7以外のレジスタを指定することより、サブルーチン内でリンケージ・レジスタの値を変更して、戻り番地以外の場所に戻ることができます。こんな機能は役に立つのかと疑うのも無理はないと思いますが、連載の後半で、リンケージ・レジスタを使ったサブルーチンの例を解説する予定です。
(5匹のカタツムサブルーチン版の巻へつづく)
※コメント投稿者のブログIDはブログ作成者のみに通知されます