ratfor on unix/v6
ある夜、佐川さんが荷物を持ってきた。女房が通販で頼んだ物みたい。嬉々として荷物を解く女房。 何が出てきたかと言うと、ポテトチップス製造機(with 餅焼き網)
スリットが28本入った皿みたいなのと、芋をスライスする鉋みたいのが付いてた。さつまいもとか カボチャとかもチップスに出来るようだ。
早速、ままごとの始まりですよ。説明書には、500Wの電子レンジで11分。800Wで7分チンして くださいなんて書いてある。我が家にある石釜オーブン付き電子レンジは、牛乳と冷や飯の 暖めにしか使っていないから、500Wで11分なんて、どうやって設定するのやら?
面倒な事はおいらに出番が回ってくる。家中探して、取り扱い説明書を探してきた。そして、 手動設定の項目を見つけたよ。手動出力切り替えボタンを、ぽんぽん押せば、表示が代わるんだ。 そして、秒、分、10分のボタンを適当に押して、時間を設定するのね。準備が出来たら、スタート ボタンを押す。こんな使い方、初めて知ったよ。
待つ事、7分の短縮モード。焦げてる所があるかと思うと、まだ半生みたいな所もあって、 一回目は失敗。最近のレンジって、何で回転しなくなっちゃったの? 何か退化してるぞ。 2回目は、11分モードで、途中手動回転させませたよ。レンジの蓋を開けると、もうもうと 蒸気が出てきて、やけどしそうになった。排気はどうなってるん?
今度は、うまく出来たようだ。黒胡椒入りの塩を振りかけて、ビールと一緒に楽しみましたよ。 ああ、また太ってしまうぞ。
いろいろな言語(bas)
前回 unix/v6にbasicが入っている事を確かめた。どんな風に出来ているかと確かめてみると
# grep bas CATLOG /bin/bas /usr/source/s1/bas.s /mnt/man/man0/basinf /mnt/man/man1/bas.1 # cd usr/source/s1 # wc bas.s 2113 3916 bas.s
/binの下とは、いい席を確保してるなあ。あの頃はbasicは幅を利かせていたんだ。ソースの サフィックスに.sが付いているって事は、アセンブラか、2100行ねえ。バイナリーサイズを 調べたら、8k Basicだったよ。
おいらが始めて触れたミニコンには、2種類のBasicが付いていた。4kの方は、普通のBasic。 コアメモリーが8Kあると、8kバージョンのBasicが使えた。行列演算をサポートしてて、行列の 掛け算とかやらせて、ああ、数学の通りに動いてるって、歓心したものだ。
確か東大の森口先生が書いた入門書が出てて、会社で一括購入してくれた事を覚えている。そして、 その中に問題集が付いていて、ピタゴラスの三角形を求めよとか、うさぎときつねの問題 (うさぎが増えるとそれを餌にするきつねも増え、きつねが増えすぎるとうさぎの数が減るという、平衡問題) を解けとか、無い頭を絞って、勉強したなあ。1970年頃の話だけど。
mov $1f,r0 jsr pc,print br loop 1: <Cannot open file\n\0>; .even print: mov r0,wbuf jsr pc,size mov r0,wlen mov prfile,r0 sys indir; syswrit rts pc syswrit: sys write; wbuf: 0; wlen: 0
一部を出してみた。あの頃のアセンブラって、文字列は、三角括弧で囲んで表して、NULL ターミネートだったのね。これぐらいなら、すらすら動作を読めるけど、さすが、2000行を 嫁と言われると辛いなあ。
いろいろな言語(as)
上でも出てきたけど、sysの正体って一体何よ? pdp-11のハンドブックをみると、それらしい のに、emtとかtrapとかあるけど、sysって言うのはDEC用語にない。はてどう調べよう。 asコマンドにアセンブラリストを出力するオプションも無いし。。
# cd /usr/source/as # wc * 106 198 as11.s 70 125 as12.s 131 246 as13.s 231 446 as14.s 170 284 as15.s 291 498 as16.s 220 382 as17.s 65 112 as18.s 347 669 as19.s 258 526 as21.s 151 308 as22.s 165 307 as23.s 113 237 as24.s 4 6 as25.s 559 1028 as26.s 294 589 as27.s 77 120 as28.s 280 543 as29.s 9 26 run 3541 6650 total
アセンブラもアセンブラで書かれているし。。(じゃ、それをアセンブルするのは、どうする? と言う、哲学問題には、目をつぶる)調べるのやだな。で、ふと思ったね。
# cat check.s emt 14. trap 14. sys 14. # as check.s check.s u 0001 u 0002
あら、このアセンブラは、emtもtrapも受付ないよ。そんなにDECが嫌いだったん? しゃーない、 こうなったら、人間逆アセンブラするしか。
# cat check.s sys 16. sys 15. sys 14. # as check.s # od a.out 0000000 000407 000006 000000 000000 000000 000000 000000 000000 0000020 104420 104417 104416 000000 000000 000000
16.のように、数字の最後に ドットを付けると、10進数とみなされる。何もつけないと8進数と なるのかな。オクタルダンプって、pdp11用のダンプだったんですねぇ。で、1044xxってのが 3つ並んでいるので、これは、sysですね。ハンドブックを調べると、そう、DECで言うtrap 命令でした。ついでに、XXの所は、00-377まで(すなわち256種のトラップバリエーション)指定出来ます。
trap命令の動作は、PSWとPCをスタックにセーブし、34番地の内容をPCに転送、36番地の内容をPSWに 転送するんだ。これが、システムコールの元になるハードの動きね。
ついでに、a.outのフォーマットは、最初(407)はマジック番号、text,data,bss,symbolサイズ、続いて、エントリポイント (常にゼロ)、未使用、フラグとなっている。実際のデータは、16バイト目からとなる。
マジック番号の407は、pdp11語に翻訳すると、7ワード先へ飛んでけ(PC相対のJump)と言う事で、これは、取りも なおさず、a.outのヘッダーをスキップして、データが格納されている所から実行せよと言う 事だ。昔は、こういう風に合理的だったのね。
Bill Joyも自分の生年月日を覚えてもらって 、誕生日祝いを貰いたく、ファイルシステムのマジック番号にしてる。(ちなみに彼の誕生日は、 1954年01月19日、#define FS_MAGIC 0x011954)
# size a.out 6+0+0=6 (6) # size /bin/bas 8064+700+15254=24018 (56722)
basって、変数エリアたくさん使うのね。
いろいろな言語(sno)
pdfになったマニュアルを見ていると、いろいろな言語が列挙されている。snoとか言うのが あった、どんなものか調べてみたよ。
よう分からん言語だ。awkの前身? でもなさそうだし。作者がこれに変わる言語 Icon とか いうのを作っているようだけど、これって、matzさんも注目してたよね。
# sno Unix is long term OS. ## <--- input from keyboard 1 eof on input ## <--- Ctrl-d 0 f 0 s 0 end 0 start 0 define 0 return 0 freturn 3 syspit 4 syspot 2 Unix 0 is 0 long 0 term 0 OS.
いろいろな言語(ratfor)
binの下を探検してたら、rc なんていうコマンドに遭遇した。 rc ったら、普通、run commandと思ってしまうよね。 ところが、見事に予想が外れましたよ。
変な言語 ratfor用のコンパイラーですって。ratforは、合理的なFortranの略だそうです。unix/v6には既に fortran コンパイラーが搭載されています。何年式って言われたら、fortan75とでも言えばいいのでしょうか。 で、ratforは、fortaranの語彙の貧弱さを補うために開発された、ラッパーです。
このrator、どこかで聞いた事があるぞと思って調べてみたら、『ソフトウェア作法』の使用言語に なっていました。私もこの本持ってました。1987年に購入してました。懐かしくなって、パラパラみてました。
訳者(木村 泉)さんの前書きに、この本を出版するにあたり、久野靖君達には、多大な重労働を させてしまった。感謝している。なんてくだりが出ていた。以前、茗荷谷の赤ちょうちんで 久野先生から聞いた苦労話と重なったよ。先生曰く、日本語の写植をやるために、学校と メーカーの間を、山の手線を乗り継いで、MTを運んだと。それで、木村先生が、潔癖な方で 何往復もした(させられた)と。
早速動かしてみる。題材は、ports/lang/ratforにあったテストコード。
# cat test.r integer x,y x=1; y=2 if(x == y) write(6,600) else if(x > y) write(6,601) else write(6,602) x=1 while(x < 10){ if(y != 2) break if(y != 2) next write(6,603)x x=x+1 } repeat x=x-1 until(x == 0) for(x=0; x < 10; x=x+1) write(6,604)x 600 format('Wrong, x != y') 601 format('Also wrong, x < y') 602 format('Ok!') 603 format('x = ',i2) 604 format('x = ',i2) end
format文があったりで、Fortranの姿が見え隠れする不思議が言語です。現代なら、Javaの 文法が見え隠れする、Scalaとかに匹敵するんですかね? 時代が変わっても、人間の考える事に 進歩は無いなあ。
# rc -f test.r test.r: MAIN.f: # ls -l total 22 -rw-rw-rw- 1 root 962 Jul 20 18:41 MAIN.f -rwxrwxrwx 1 root 7644 Jul 20 18:41 a.out -rw-rw-rw- 1 root 1036 Jul 20 18:41 test.o -rw-rw-rw- 1 root 436 Jul 20 18:35 test.r
Fortan経由で、最終binaryまで一機に作ってみました。展開して出来たFortanのソースが 元ファイルの2倍になってる事からすると、生産性は2倍だったんでしょうかね? 見方に よってはDSLとかマクロとかにも見えるな。
# cat MAIN.f integer x,y x=1 y=2 if(.not.(x .eq. y)) goto 23001 write(6,600) goto 23002 23001 continue if(.not.(x .gt. y)) goto 23003 write(6,601) goto 23004 23003 continue write(6,602) 23004 continue 23002 continue x=1 continue 23005 if(.not.(x .lt. 10)) goto 23006 if(.not.(y .ne. 2)) goto 23007 goto 23006 23007 continue if(.not.(y .ne. 2)) goto 23009 goto 23005 23009 continue write(6,603)x x=x+1 goto 23005 23006 continue continue 23011 continue x=x-1 23012 if(.not.(x .eq. 0)) goto 23011 23013 continue continue x=0 23014 if(.not.( x .lt. 10)) goto 23016 write(6,604)x 23015 x=x+1 goto 23014 23016 continue 600 format(13hWrong, x != y) 601 format(17hAlso wrong, x < y) 602 format(3hOk!) 603 format(4hx = ,i2) 604 format(4hx = ,i2) end
おーーーー。懐かしい(Fortranはよく知らないけど)Fortranだ。高校生の頃、NHK教育TVで フォートラン講座をやってて、毎週見てた記憶があるぞ。
# ./a.out Ok! x = 1 : x = 9
実行結果は面白い事は何も無し。走りましたね、ぐらいかな。それじゃつまらないので、 rcをちょいと紐解いてみますか。
/usr/source/s2/rc.cにあるのは、コンパイラードライバーでしょう。本命は、/usr/source/ratの 中でしょうね。
# cd /usr/source/rat # ls -l total 30 -rw-r--r-- 1 bin 5164 Jan 1 1970 lex.c -rw-r--r-- 1 bin 864 Jan 1 1970 r.g -rw-r--r-- 1 bin 132 Jan 1 1970 r.h -rw-r--r-- 1 bin 4476 Jan 1 1970 r1.c -rw-r--r-- 1 bin 1612 Jan 1 1970 r2.c -rw-r--r-- 1 bin 114 Jan 1 1970 run # cat run yacc r.g cc -s -O r1.c r2.c lex.c -ly -lp cmp a.out /usr/lib/ratfor cp a.out /usr/lib/ratfor rm *.o a.out y.tab.c
ratforと言う、Fortranへの変換機はライブラリー扱いになるのね。それを、rc.cの中から 呼び出す仕組みか。
# cat r.g %term LCURL RCURL LPAR RPAR SCOL DIGITS %term XIF XELSE XFOR XWHILE XBREAK NEXT %term OLDDO NEWDO %term XGOK XDEFINE XINCLUDE %term REPEAT UNTIL %% statl : statl stat | ; stat : if stat ={ outcont($1); } | ifelse stat ={ outcont($1+1); } | while stat ={ whilestat($1); } | for stat ={ forstat($1); } | repeat stat UNTIL ={ untils($1); } | XBREAK ={ breakcode($1); } | NEXT ={ nextcode($1); } | newdo stat ={ dostat($1); } | OLDDO ={ docode(0,$1); } | XGOK ={ gokcode($1); } | SCOL | LCURL statl RCURL | label stat | error ={ errcode($1); yyclearin; } ; label : DIGITS ={ outcode($1); outcode("\t"); } ; if : XIF ={ ifcode($1); } ; ifelse : if stat XELSE ={ outgoto($1+1); outcont($1); } ; while : XWHILE ={ whilecode($1); } ; for : XFOR ={ forcode($1); } ; repeat : REPEAT ={ repcode($1); } ; newdo : NEWDO ={ docode(1,$1); } ; %%
この辺は、青木さんのc♭にも出てきたような。。今だと、前橋さんかな。嗚呼、matzさんも これの大型判と取り組んでいるのね。(ruby-1.9.Xのparse.yは、優に10000行を超えてるよ。恐ろしや!)
言語じゃないけど、(simh)
pdp11のシュミレータなんだけど、manもinfoも付属していない。なんてこったい、なんだけど 、そんなのソース嫁。読んでみたら、scp.cに、それらしいコメントが書いてあった。RMSなんて 人の名前も、よく登場してるんだけど、あの人? とにかく、メモリーの検査とレジスターの 値確認ぐらいは、出来なければね。
Simulation stopped, PC: 021630 (MOV (SP)+,177776) sim> e 30-40 30: 000746 32: 000345 34: 000746 36: 000346 40: 000167 sim> e 746/20 746: 016767 750: 177024 752: 040620 754: 005767 756: 040602 760: 001017 762: 016767 764: 176604
最初の例は、30番地から40番地まで検査。次の例は、746番地から20byte(8進数で)までの 表示です。逆アセンブルもしてくれるといいのに。
sim> ie state PC: 021630 R0: 140004 R1: 034272 R2: 005262 R3: 000200 R4: 000000 R5: 141724 SP: 141710 R00: 140004 ^Dsim> e psw PSW: 030000
レジスターの値を順番に表示(CRで次)ほっておくと大量のレジスターを表示してしまうので、 途中でCtrl-dを使って表示を中止して、新たに、PSWだけ表示してみた。
後便利そうなのが、break -e address で、ブレークの設定。nobreak で、解除かな。それに 加えて、ahow breakで、BPの確認。stepで1命令づつ実行(止まった時、逆アセンブル表示) もしてくれる。 そこまで、使えるようになったら嬉しいな。
sim> break -e 746 sim> c Breakpoint, PC: 000746 (MOV 177776,41574) sim> break 746;
とか、言いながら、使ってしまったよ。これは、面白い。更に面白いのも有って
sim> set cpu history=100 : ## running unix, then Ctrl-e sim> show cpu history=20 PC PSW src dst IR 034372 030000|000003 034372 SOB R4,34316 034316 030000|034316 005206 ADD #26,R2 034322 030000|034322 005234 CMP #7322,R2 034326 030000| BHI 34334 034334 030000|034334 005234 CMPB #3,(R2) 034340 030000| BNE 34372 034372 030000|000002 034372 SOB R4,34316 034316 030000|034316 005234 ADD #26,R2 034322 030000|034322 005262 CMP #7322,R2 034326 030000| BHI 34334 034334 030000|034334 005262 CMPB #3,(R2) 034340 030000| BNE 34372 034372 030000|000001 034372 SOB R4,34316 034374 030000| 034374 TST 41576 034400 030004| BNE 34414 034402 030004|005262 034402 MOV R2,41576 034406 030000|034406 034406 JSR PC,21620 021620 030000|021620 141712 MOV 177776,-(SP) 021624 030000| 140004 SPL 0 021626 030000| WAIT
これ、pdp11の実行履歴ですね。どこを回っていたか確認出来るよ。
なお、simhについては、 simhの日本語解説 や 英文マニュアルが 参考になります。
最後に、cobolが無いのは肯けるけど、lispが入っていないのは、なして?(ぼそっ) 調べてみたら、 ここで歴史 が説明されてた。そして当たりを付けて lisp に辿りついたよ。