SSECの周辺装置
目次
アセンブル
さて、SSEC は 20桁の数値による命令を、2本の紙テープに間違いなく並列に、BCD を意味する2進数で記述しなくては動きません。
そんなややこしい作業は、人間にはとてもできません。
そこで、プログラム自体は、もう少し簡単に出来るように工夫されていました。
IBM らしく、パンチカードを使う方法です。
命令は相変わらず数値ですが、2進数に変換する必要はありません。
また、同時に読み込み・実行される命令を、別々に記述する必要もありません。
パンチカードは、横に80桁、縦に 12の穴が空けられました。
この右半分、40桁の部分を使い、縦10個の穴を数値の 0~9 と見做して、直接パンチすればよいのです。
カードには直接フィールドの区分が記述され、目的の数字の位置に穴を空けるようになっています。
左半分は使用していませんから、プログラム名称や、命令を(手書きで)書き込むようになってました。
また、使用していない部分なのでプログラムの「行数」を連番でパンチしておくことで、カードがバラバラになってもソートできました。
プログラムが完成したら、カード読み取り機に読み取らせ、数値を BCD に変換して、紙テープパンチャが、プログラムの紙テープを生成します。
これで、「ソースプログラム」を元に、「アセンブル」して、実行バイナリが作り出されます。
もちろん、当時はまだアセンブラという概念はありません。
しかし、人間にわかりやすい方法で記述して、機械が理解できる「2進数」に変換する仕組みが作られていたのです。
しかし、SSEC 自身にやらせるのが一番簡単ではないかな、と思ってます。パンチカード幅の紙テープ装置って特殊で、多分 SSEC 以外に使っていなかったし。
別に、アセンブラがあったとかいう話ではなく、0~9の穴を BCD に変換してパンチするだけの話です。プラグの差し替えだけで対応できたでしょう。
実際のプログラム例
特許書面に記載されている、ニュートン法で平方根を求めるプログラムを解析してみましょう。
とりあえず、ニュートン法が何かはどうでもいいです(笑)
条件判断しながら繰り返すプログラムだと理解してください。
マーク1では、このようなプログラムは作れませんでした。
少し画質が荒れているのはご容赦ください。
なにぶん古い特許で、他のスキャン画像を当たっても同じような滲みがありました。
元の書類が汚れてしまっているようです。
例では、数式を添えて記述していますが、これは説明用。SSEC に与える命令は数字部分のみです。
S1 / S2 が横に並んでいます。実際、先に「アセンブリ」として書いたように、プログラムをする際は並べて書いたためです。
前提条件として、このプログラムは「サブルーチン」で、紙テープはループしています。
終わった後は呼び出し元に戻るか、ループによって先頭に戻ります。
命令格納装置の 21,22,31,32 はテープ装置です。
21,22 はサブルーチン、31,32 は呼び出し元のプログラムです。
また、末尾22,32 は S1 、21,31 は S2 のプログラムを格納しています。
命令格納装置の 52 と 53 は、リレー装置の 152,153 を示しています。
157 はリレー装置ですが、細工がしてあり、一番最後の1桁だけ、プラグ記憶に接続されています。
つまり、その部分は書き変わりません。
赤・緑・青で枠線を書いていますが、これは僕が描き入れたものです。
プログラムを、意味ごとにブロック分けしています。このブロックごとに話を進めます。
以下、説明を読みやすいように、同じプログラム画像を繰り返し表示します。
まずは赤のブロックから解説します。左上、右上、下の行…とプログラムは進みます。
最初の命令、除算命令を使って N/X を求めているだけです。
この際、X はレジスタ 5を使って リレー記憶 031 から読み出しています。
また、結果はレジスタ 2を経由してリレー記憶 032 に入っています。
続く命令では、いま値を入れたレジスタ 2 と 5 を足して、レジスタ 3 を経由して リレー記憶 33 に入れています。
X + N/X が求まりました。
さらに、いま求めたレジスタ 3 を、プラグ記憶 614 に設定された定数「2」で割っています。
この結果 (X + N/X)/2 は、レジスタ5を経由して、リレー記憶 129 に入ります。
ここまでで、ニュートン法の計算としては1段落。
「前回の」値を元に「精度を上げた」新たな値を求めたことになります。
プログラムでは、レジスタを上手に利用して、周辺装置へのアクセスを軽減していました。
高速化のための重要テクニックです。
さて、続いて緑のブロック。求めた値の精度の検証です。
まず、いま求めたレジスタ 5のデータ転送を、シフト付きで行っています。
データ転送だけなので、データは送信元と送信先だけで十分です。
そのため、T のフィールドは完全に空白になっています。
転送時に5桁シフトしているので、100000 で割ったことになっています。
結果に対して 0.001% 。これが、許容される誤差となります。
次に、レジスタ 5のいま求めた結果から、リレー記憶 031 の値を引いています。
リレー記憶 031 って、最初に出てきた X の値です。
これで、前回の値と、新たな値の差を求めたことになる。「誤差」はこの差以下に収束しています。
さらに、先ほど求めた「許容誤差」と、いま求めた「誤差」を絶対値で引きます。
結果がプラスなら、平方根が許容できる誤差で求まったことになります。
さて、これで誤差の検証は終わりなのですが、この結果を使って分岐しなくてはなりません。
青で示される部ブロックです。
先ほど精度を求めた際に、結果を「19桁右シフト」する指示がついていました。
SSEC は符号付 19桁しか扱えませんから、結果がどんな値であっても、 0 になります。
ただし、符号は別になっているので、+0 か -0 です。
この結果は、リレー記憶の 157 に入れられています。
その直後、再びリレー記憶の 157から読出しを行っています。
今書き込んだ内容ならレジスタに残っているのに、なぜわざわざ読み込むのでしょう?
先ほどの前提で、「157は1の位だけプラグ装置に繋いである」と示しました。
実は、ここに、固定値の「 5 」が設定されています。
しかし、符号部分はリレーに保持されているので、先ほどの ±0 を書き込んだ影響を受けます。
続く2命令では、この値を 27,26 という固定値と足して、リレー記憶の 152,153 に入れています。
32か22、31か21 が書き込まれることになります。
この番号は命令格納装置のもので、「呼び出し元」か「現在のサブルーチン」になっています。
精度が十分なら呼び出し元に戻り、精度が不十分なら繰り返し計算を行う、という分岐を行うのです。
そして、今書き込んだリレー記憶に制御を移します。
S1 側にはもう命令は無く、命令装置番号に 52 を指示しているだけです。
S2 側では、いま求めた「結果」を、次の計算に備えて「1つ前の結果」にコピーしてから、53 に移行します。
もちろん、52 / 53 から読み出した命令は、先に書き込んだ数値…条件分岐先の指示のみです。
プログラムを読み込む装置は「一番下の桁」に書かれるので、自己書き換えが可能となっています。