2014年9月24日水曜日

割込み

私が2年ほど前にツィートした割込みの話がいまでも時々リツィートされているようだ.

今日はその割込み(英語ではinterrupt)の昔話しを書いてみたい.

私がいた研究室, つまり東大物理学科の高橋研究室では, 院生の後藤さんが発明したパラメトロンを使って計算機を自作した. 1958年のことである. Parametron Computer No.1ということで, 通称はPC-1という.

当時計算機とかプログラミングでは, 英国ケンブリッジ大学のEDSACの本があったので, 計算機を作ろうとすると, EDSACが手本であった. PC-1ではEDSACのアーキテクチャを十分検討し, ほとんどそのまま採用したものもあれば, 我々の哲学に従って変更したものもある.

入出力命令も変更した部類であった.

EDSACの入力命令 I n は, 5単位紙テープの1列を, n番地の右端に読み込む; 出力命令 O n は, n番地の左端の5ビットを書き出す. しかしこれは不便ではないかと我々は考えた. 読み込んだ文字コードを調べるには, これを演算装置, アキュムレータに取り出さなければならい. また文字コードをアキュムレータで作ってから書き出すこともあろう. そういうわけで, PC-1で は, 入出力はアキュムレータを経由することとした. さらに入力はアキュムレータの左端に入れることにした. そうするとサインビットの判定も楽だからだ.

もちろん, 入力命令コードは i, 出力は o である. ではこれらの命令の番地部は何に使うか. 計算機の処理速度に対して, 入出力は遲いから, 計算機は次々と入力や出力を続ける際, 待たされることになるだろう. そこで入出力命令を実行しようとした時, 相手の機器の準備が出来ていなければ, 別の計算に移れるように, 命令の番地部へとぶようにした. つまり条件ジャンプ命令にしたのである.

入出力をしながら, 同時に計算も出来るということで, 聖徳太子は十人の訴えを同時に聞いたと伝えられるから, この機能には聖徳太子というあだ名がついた.

しかし, 実際問題として, こういうプログラムを書くのは結構面倒である. 従って普通には命令は自分の番地にジャンプする, つまりダイナミックループをするように書かれていた.

下がPC-1が最初に実行したプログラム(neglect erase)である. 当然だが二進法で紙テープに穿孔してある.

0    i 0;
1    b 6;
2    zl 0;
3    b 6;
4    o 4;
5    jl 0;
6    111111000...0;

0番地のi命令の番地部は0, 4番地のo命令の番地部は4になっている. このプログラムは紙テープを読みそのまま出力テープに複写するが, 抹消のコード(6単位がすべて1, つまり全穿孔)は複写しない. 6番地には左端6ビットに1が入っており, 1番地のb命令でビット毎のxorをとり, 結果が0ならzl 0;で0番地に戻る. そうでなければ3番地で元に戻し, 4番地で出力, 5番地で0にジャンプバックする.

入出力と演算の同時実行のプログラムがなぜ面倒かというと, 入出力機器の準備ができていなくて演算をしていると, 今度は準備が出来たかどうかを絶えず見にいかなければならず, それはまた煩わしいのである.

例えていえば, なるべく早く食事したいが, 食堂がまだ準備中なので本を読んでいるとする. しかし食堂が開いたかどうか, 絶えず注意していると, 本を読むのも途切れ途切れで能率が悪い. 能率よく本を読みしかもすばやく食事にありつく対処法は食堂の準備が出来た時, 食堂の方から知らせてくれることである.

というわけで, 入出力機器, といっても出力のテレタイプの方だけだが, 準備ができたらプログラムに知らせる機能をつけることにした.

どうやってプログラムに知らせるか, プログラムの実行中の情報をどう保存するかを次に考えることになった.

PC-1の記憶装置は512語であったので, 510番地に次に実行する命令の番地をいれ, 511番地にジャンプすることになった. 割込む機器は1台であったが, 複数台になったとき, 割込みが続けておきると, 帰り番地の情報が失われる恐れがあるので, 割込みと同時に, その後の割込みを禁止する. この禁止はプログラムで解除する.

PC-1にはプログラムでセット, リセットできるフリップフロップが2個あった. 2014年3月13日の私のブログ「計算機による音楽演奏」で使ったのもこのフリップフロップである. その一つを割込み禁止に使った.

では割込み処理の説明に移ろう.

なにか長い計算をしていて, 途中時々数値を出力しているとする. 出力サブルーチンはその数値を十進法に変換し, そのそれぞれの数字や記号をテレタイプのコードに変換してテレタイプに送りだすのが通常の処理である.

それに対し, 割込みではコードに変換するまでは同じだが, それを1文字ずつリングバッファに入れるのである.

下の図が当時の割込み処理の流れ図である.



出力サブルーチンは, コード変換がすむと, 流れ図の左上からこの処理に入ってくる. まず割込みを禁止し, 帰り番地を510番地に設定する. 次に出力すべきテレタイプのコードをリングバッファに入れ, 入り口の指標indexを1増やす.

それから中央の線へ行き, 出口の指標exdexの指す一番古いコードをアキュムレータに取り出し, o 命令を実行する. 出力機器の準備が出来ていれば出力でき, yesの口から出る. 反対に準備がまだならnoへ出, バッファが満杯かどうかを見る. 満杯なら仕方ないから, 先程の古いコードを取り出すところへ戻り, 機器の準備を待つ. 満杯でなければ, 次のコードを入れられるから, 下へ抜けてもとのプログラムへ戻る.

1文字出力出来た場合は, 中央の線の一番上へ戻り, 出口の指標exdexを1増やす. バッファが空なら戻る. 空でなければ一応出力してみようと 試みる.

割込み処理から戻るときには, 割込み禁止を解除しておく.

一方割込みが掛かって処理ルーチンに来るときは右上から入る. この時は帰り番地の設定は済み, 割込み禁止も掛かっているが, なにかの実行中で飛んできたので, アキュムレータや他のレジスタ類を退避してから 出力のループに入る.

簡単だがこれはいちおうマルチプログラミングである. この実験をやったのは1959年の夏ころと思う. ちょうどその頃, パリでUNESCO主催のコンピュータの会議があり, Christopher Stracheyが割込み, マルチプログラミング, TSSの提案をしていた. 我々はその割込みを先取りしているので大いに気持ちがよかった.