2026-04-20

PDP-11のハードウェアTRAPにおけるモデル差異

PDP-11/40で動作するUNIXv6を、Lions本を頼りに学んでみようと考えています。まず手始めに「low.s」を調べています。この中でトラップベクタが定義されていますが、PDP-11のモデルによって違いがあるのではないかと気になりました。カーネルの動作環境は、SIMHのPDP-11エミュレータを使用するつもりですが、PDP-11/40を想定しています。しかし、PDP-11/45とかPDP-11/70という環境を考えることも、できなくはありません。PDP-11のモデルは他にもありますが、まずは11/40、11/45、11/70を考えると、モデルによる差異はどうなっているのでしょうか。

 

調査した資料は、PDP-11/40、11/45、11/70の『Processor Handbook』です。

 

まず、4番地から34番地にある7つのTRAPは、どのモデルにも存在します。また240番地と244番地の2つのTRAPも、どのモデルにもあります。しかし250番地のTRAPは、PDP-11/45、11/70にしかないようですし、114番地のTRAPは、PDP-11/70だけにしか存在しません。「low.s」では、これらのTRAPが全て定義されていますが、定義されていても別に無駄にはならないので、問題ではないのでしょう。

 

また各トラップベクタでは「trap; br7+5」のように記述されています。PDP-11のトラップベクタは、2ワード(4バイト)で構成されており、第1ワードが飛び先アドレス、第2ワードがPSWです。そして「br7」というのは割り込みのプライオリティを示していますが「+5」は何でしょうか。「low.s」の中では「br7+0」から「br7+9」まであります。

 

「trap」とは、「m40.s」の中にあるラベル「trap」のことで、Lions本の0755行にあります。この中で更に制御が移り、「trap.c」の「trap()」が呼ばれます。これはLions本の2693行にあります。ここで「+5」などを処理するために、switch-caseがあります。ただし「br7+4」と「br7+7」に相当するcase文はありません。これらはdefault文で処理されることになります。

 

しかも「low.s」には「br7+7」となっているトラップベクタが2つあります。Lions本の0538行と0547行です。これらは、「trap()」でも対応するロジックがありませんから、UNIXv6としては、未対応で十分という判断なのだと思います。今回UNIXv6のカーネルを学ぶに際しても、それ以上の調査は行いません。ただし将来的には、これらのTRAPの扱いがどうなっているのか、調べてみたい気がします。UNIXv7とかBSD2.11などでは、改良されているのでしょうか。それとも手付かずのままなのでしょうか。 

「4」とは?

PDP-11/40で動作するUNIXv6を学び始めました。カーネルを学ぶ入口は様々かと思いますが、まずは起動する過程を追いかけていこうと考えています。参考書はLions本で、オンラインで参照できる様々な資料も使います。実行環境は、実機があればよかったのですが(よくない?)、SIMHのPDP11エミュレータを使います。

 

カーネルの0番地に関連するのは、「low.s」です。Lions本では500行から599行までです。508行の0番地には「br 1f」があり、522行には「1: jmp start」があるので、カーネルの起動処理は、実質的には「start」から始まっているようです。

 

ここで509行目に目を移すと「4」とあります。これは何でしょうか?PDP-11の命令ではないし、疑似命令でもありません。何かの定数宣言でもなさそうですし、コメントが入っていないので、意図も分かりません。

 

『PDP-11/40 processor handbook』の「APPENDIX B MEMORY MAP」 には「INTERRUPT VECTORS」として、0番地から300番地あたりまでに定義されている割り込みベクターが記載されています。これらは、2ワード(4バイト)を組みとして、第1ワードが飛び先アドレス、第2ワードがPSWの設定内容となっています。ただし0番地は「RESERVED」となっているため、ここが割り込みベクターとはなっていないし、実際に「br 1f」という命令が置かれているわけです。仮に割り込みベクターと考えたとしたら、PSWが入るはずの場所に「4」があるわけですが、そもそも割り込みベクターではないので、PSWに設定する値ではないはずです。

 

「low.s」では、512行から「trap; br7+0」のように、PDP-11/40が定義した割り込みベクターが並んでいます。これらは4番地から始まるので、0番地の「br 1f」だけでは番地がずれてしまうので、何か埋め草が必要です。それが「4」のように見えるのです。

 

この「4」には、何か意味があるのでしょうか。「0」でも構わないのではないでしょうか。もしくは「4」を記述せずに、「. = 4^.」を明示した方が良かったのではないでしょうか。この疑問には答えがありません。強いて言えば開発者本人に聞くしかありませんが、もう60年くらい前のことですし、強いて思い出してもらわなければならないほど重要な問題でもありません。 

「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が変化するのを期待しているわけではありません。 

2026-04-16

Lions本とUnix-v6-Ken-Wellsch.tapとではデバイス構成が異なる

SIMH上のPDP-11エミュレータでUNIXv6カーネルを学ぼうと考えています。まずは、「low.s」と「m40.s」から手を付けていきます。参考書は、オンライン上の資料もありますが、やはり定番のLions本です。UNIXv6環境は、「Installing UNIX v6 (PDP-11) on SIMH」に従い、「Unix-v6-Ken-Wellsch.tap」を利用するつもりです。

 

「low.s」は「mkconf.c」により生成されるものなので、UNIXv6のソースツリーには含まれていません。Lions本には「low.s」が掲載されていますが、これがSIMH上の環境と合っているとは限りません。まずSIMHのデバッガ―を利用して、メモリ上に置かれたカーネル「rkunix」を調べてみました。

 

確認したところ、カーネル「rkunix」は、以下のデバイスを有効にしていると見られます。これは「run」の内部で「rkunix」を生成する箇所と一致します。

  1. RK11
  2. TM11
  3. TC11 

 

一方で、Lions本は、0500番台の行番号がついている「low.s」によれば、以下のデバイスが有効になっています。

  1. RK11
  2. LP11
  3. PC11

 

ディスク操作は、どちらもRK11ですが、端末関係が違います。このような違いも含めて、UNIXv6のカーネルを学んでいこうと思います。 

2026-04-15

「国際電話不取扱受付センター」というものがあるらしい

自宅の固定電話に着信するのは、不審なものばかりです。ナンバーディスプレイを契約しているので、相手先の番号がわかるのですが、「0120」とか「0800」などの国内から発信されたもの以外に、番号体系が「0AB~J」や「0A0」にはなっていないものが増えてきています。おそらく海外から発信されたものなのでしょう。

 

不審着信は無視しているし、同一番号からの着信が多い場合は、ブロックリストに入れて着信音が鳴らないようにしています。このような対策をしているのですが、物は試しとGeminiに相談してみました。すると「国際電話不取扱受付センター」という存在を教えてくれました。ここに登録しておけば、海外からの着信を全て拒否するようになるそうです。

 

こんなものがあるのかと思いました。これを申し込んでも海外に発信することはできるそうですし、海外からの着信を受けたくなれば、登録を解除することもできるそうです。実際に登録を申し込むかどうか分かりませんが、考えてみようと思います。

2026-04-12

復活したブラタモリは普通のブラタモリ

2024年3月で終了となった「ブラタモリ」が 、2025年4月からレギュラー放送に戻りました。復活前には「番組のコンセプトはそのままに、街道を歩くシリーズものなど、新しい試みにも挑戦し、より幅広い世代の人に地域の魅力を届けます。」という発表がNHKからありました。

 

復活直後は、シリーズで街道を取り上げていましたが、しだいに昔ながらのブラタモリに戻っていて、いまはもう普通のブラタモリになっている気がします。2026年4月には皇居内に入ったので「新しい試みに挑戦」とも言えるかもしれません。しかし「街道」はどうしたと言いたいところです。 

2026-04-11

SIMHを使用してUNIXv6カーネルを学ぶための準備

SETTING UP UNIX - Sixth Edition」に記述されている「Making a Disk From Tape」と「Booting UNIX」の手順について、内部処理を確認してきました。これをおこなうことで、UNIXv6のソースファイルにも、PDP-11の動作についても、分かってきました。さらにSIMHのPDP-11エミュレータ内蔵デバッガについても、理解が進みましたので、いよいよカーネル本体を学ぶ練習としては、ちょうど良かったと思います。

 

これからカーネル本体について学んでいきますが、Web上の様々な情報を参照するつもりですが、主たる参考書はもちろんLions本です。ソースファイルを参照するには「The Unix Heritage Society」のサイトにあるものを使おうと考えています。

 

カーネル本体は、これまで見てきたブートローダに比べると大きいし、アセンブラではなくC言語が使われています。SIMHのデバッガは、UNIXv6カーネルのシンボル情報を参照できません。闇雲にデバッガを操作しても、深みにはまるだけで、何も得られないと思います。なんとならないかとGeminiに相談したら、コマンド「nm」を使って、シンボル情報リストを入手しておくことを勧められました。「nm -n rkunix」を実行して得られたリストを手元に置いて参照することにしました。今の時代なら、シンボリックデバッグを使えばローカル変数でも何でも参照できますが、UNIXv6時代では、そこまで求めることはできません。でも、関数のエントリポイントのアドレスが分かるので、最低限の参考にはなりそうです。

 

カーネルの調査を進めていくため、調べたこと、分かったこと、分からないこと等々を記録していく必要がありますが、TW5を利用するつもりです。取得したシンボルテーブルもTW5に記録しておくつもりです。そのままでもシンボルを検索できないわけではないと思いますが、もう少しなんとかならないかと思います。Geminiに相談したら、簡単なスクリプトを生成してくれました。これを使えば、検索ボックスでシンボル名かアドレスを入力すると、対応するアドレス(またはシンボル名)を見つけてくれます。ミニツールではありますが、便利に利用できそうです。