2026-04-20

「klin: jsr r0,call; _klrint」とは何をしているのか

Lions本や、オンライン上にある情報を参考に、PDP-11/40で動作するUNIXv6について学んでいます。まずはカーネルが起動する過程から調べていこうと思い、「low.s」を見ています。これは機械的に生成されたものである点に注意しておかなければなりません。実行環境は、当然ならが実機を所有していないので、SIMHのPDP11エミュレータを用いて、「Installing UNIX v6 (PDP-11) on SIMH」の手順で作成された環境を利用します。 

 

Lions本に掲載されている「low.s」は、実行環境とは構成されているデバイスが違います。しかし「klin: jsr r0,call; _klrint」のようなエントリが並んでいるのは同様です。このようなロジックを考え付いた経緯はわかりません。他の実装も考えられるかもしれません。僕が疑問を感じる(と言っても、この実装が駄目だと言っているわけではないのですが)のは「JSR(Jump to Subroutine)命令を使っているのに、この場所に戻ってくることは想定していない」からです。もし本当にサブルーチンコールを意図しているなら、何らかの処理をしたら、この場所に戻ってくるわけですが、「low.s」では各デバイスのためのJSR命令が並んでいるだけですから、それを順番に処理しても意味がありません。このJSR命令は、戻ってこないのが前提であり、むしろJMP(Jump)命令のような動作を期待しているはずです。

 

さらにJSR命令の後に続く「_klrint」は何でしょうか。これは、Lions本であれば8078行にある「klrint()」のことです。そしてJSR命令で呼び出される「call」(Lions本の776行)には「jsr pc,*(r0)+」があります。PDP-11のJSR命令は、x86のCALL命令とは異なり、戻り番地がスタックに積まれるとは限りません。特に今回のように「jsr r0,call」となっている場合、戻り番地は、レジスタR0にあります。と言うことは、R0が指している場所には「_klrint」があります。つまり「jsr r0,call; _klrint」では、形式的にサブルーチンコールとして「call」が呼ばれ、その中で「jsr pc,*(r0)+」として、「_klrinit」に制御が移ります。最終的に呼び出し元に戻ってくることはありません。

 

なお「jsr pc,*(r0)+」において、R0の内容が変化しますが、これは副作用です。PDP-11に「jsr pc,*(r0)」のような指定が存在しないだけであって、カーネルとしてR0が変化するのを期待しているわけではありません。 

0 件のコメント:

コメントを投稿