エンジョイC050回目CSVの解析とJSR(2021-04-11)

1
ほえほえ@スプシマン @hoehoe1234

エンジョイC050回目CSVの解析とJSR(2021-04-11) エンジョイC、記念すべき第50回目の講座となりました。最近はC言語をほったらかして延々とアルゴリズムとOSコードリーディングをやっております。しかし、人が増えない!ということで計画発動です。 pic.twitter.com/jlpTC2o20s

2021-04-15 19:18:09
拡大
ほえほえ@スプシマン @hoehoe1234

OSコードリーディングに興味のある人もおおいのではないでしょうか?しかし、現実的に読み進められる人はごく僅かです。しかし、「教えてもらえばよめるのではないか?」との仮説で始めたこの講座、たしかに読めるようにはなるのですがやはりとっつきにくい。とうことで検討開始です。

2021-04-15 19:21:14
ほえほえ@スプシマン @hoehoe1234

興味をもってもらえることを前提に、すくなくとも ①CPUとレジスタ ②C言語 ③関数の呼び出し はわかないと何をやっているのかまったくわからないのでは?となり、GWにOSコードリーディングブートキャンプを開催することになりました。

2021-04-15 19:22:35
ほえほえ@スプシマン @hoehoe1234

実際、OSのコードリーディングはむずかしいのですが、前提条件としてかなり低い分野となります。なにより ①数学的な背景が不要(中学程度) ②高度なアルゴリズムが不要 ③FWもライブラリもなくひたすらC言語+アセンブラ となっています。数学が不要なのは大きいですね。

2021-04-15 19:25:02
ほえほえ@スプシマン @hoehoe1234

OSコードリーディングの目標は唯一です。それは「読み切って理解すること」です。それにどのような付加価値をつけるかは参加されている生徒さんそれぞれでよいと思います。私にとっては書籍執筆のネタにもなりますし、「カーネルコードを読み切る」という自分への挑戦にもなっています。

2021-04-15 19:26:51
ほえほえ@スプシマン @hoehoe1234

4日間、50時間で計画していたのですがさすがにそれはちょっと大変なので3日間、30時間の計画としました。1日8時間で組んでいますがたぶん1日10時間の3日間になるとおもいます。後日計画を配布しますのでみなさん、ぜひブートキャンプにご参加ください。

2021-04-15 19:28:21
ほえほえ@スプシマン @hoehoe1234

前回の思い出しとしてJSR命令の整理をします。形式は ①JSR reg, dest です。regはレジスタ、destはジャンプ先となります。unixで使用されているのは実質的に ②JSR PC, dest か ③JSR R5, dest になります。R5はいわゆるBP(ベースポインタ)です。 pic.twitter.com/hsgWBNX39J

2021-04-15 19:34:11
拡大
ほえほえ@スプシマン @hoehoe1234

JSRはサブルーチンを呼び出す命令(アセンブラ)です。まずはpdp11-40ブックを読んでJSRの「挙動」について理解します。黄色マーカの部分が挙動ですね。 pic.twitter.com/kgHMaA29fi

2021-04-15 19:38:08
拡大
ほえほえ@スプシマン @hoehoe1234

こいうのを読んで、理解することがやはりOSコードディリングの敷居を高くしているように感じます。実際にやってみると難しくないのですが「とっつきにくさ」はありますね。これをわかりやすく説明するために塾があるのですね。

2021-04-15 19:39:35
ほえほえ@スプシマン @hoehoe1234

日本語に意訳すると ①内部レジスタ(tmp)にジャンプ(dst)先を保存 ②スタックにレジスタ(reg)をプッシュ(↓があるのでスタックは1つ伸びる) ③レジスタにPCを代入(この時点のPCはJSR命令の次の命令を指している) ④PCにtmpを代入する となります。これが「挙動」の説明です。

2021-04-15 19:42:42
ほえほえ@スプシマン @hoehoe1234

「挙動」を追うだけでもスタックの解析はできますがストレスがたまります。なぜでしょう?それは「意味(意図)」として言語化されていないからです。言語化されていないと毎回毎回この操作をなぞる必要があります。これがストレスになるのです。これはあまり望ましくないですね。

2021-04-15 19:44:19
ほえほえ@スプシマン @hoehoe1234

本日の講義の解説をする前に、この動きの「意味」を考えてみましょう。形式は ①JSR PC, callee と ②JSR R5, callee とします。C言語から関数を呼び出す場合は①の形式が利用されます。②の形式はアセンブラから使用することになります。

2021-04-15 19:46:02
ほえほえ@スプシマン @hoehoe1234

これは本文にも説明がありますが、意味的にはサブルーチンにジャンプするのは自明として、レジスタの動きを言語化します。次のようになります。 ①使用するレジスタ(reg)をスタックにプッシュする ②regにその時点のPC、すなわち「戻りアドレス」を代入する。 ③指定されたdstをPCにセットする。

2021-04-16 02:27:05
ほえほえ@スプシマン @hoehoe1234

となります。大切なのは①と②ですね。要は「指定されたレジスタを保管のためにスタックにプッシュして戻りアドレスはそのレジスタに格納する」となります。違う言い方だと「戻りアドレスを設定するレジスタはスタックに保管しておく」となります。なのでこれがリンケージレジスタと言われます。

2021-04-16 02:28:32
ほえほえ@スプシマン @hoehoe1234

JSR R5, destの場合はこの通りの動きとなります。他の汎用レジスタでも同じですね。ただし、JSR PC, destとした場合にだけ動きの意味が異なります。PCは実行している場所そのものですので保存されるのもPC、dstが代入されるのもPCとなります。

2021-04-16 02:36:34
ほえほえ@スプシマン @hoehoe1234

手順に従い ①まずPCがスタックにpushされます(これはJSRの次の命令、すなわち戻りアドレスです) ②PCにPCがロードされます ③PCにdstがロードされます 2番めの処理は3番めの処理で上書きされるんですね。ですからdstに移動したときには環境ポインタであるBPは「セーブされていません」。

2021-04-16 02:38:45
ほえほえ@スプシマン @hoehoe1234

これがC言語規約による呼び出しで、関数の頭で push BP mov SP BP が行われる理由です。JSR R5, dstの場合はR5(BP)を保存する必要はありませんね。unixではこの違いをうまく利用してレジスタをスタックに保存しています。それがcsv関数となります。

2021-04-16 02:41:03
ほえほえ@スプシマン @hoehoe1234

ここからは『はじめてのOSコードリーディング』(以下黒本)のcaller/calleeの解説となります。この2つの関数は見ての通りの関数です。 pic.twitter.com/9DDYx3qSIX

2021-04-16 02:45:38
拡大
ほえほえ@スプシマン @hoehoe1234

caller/calleeのコンパイルされたコード(アセンブラ)となります。エミュレータでコンパイルした結果だそうですがすごいですね。当塾にはそのような環境はないのでとても参考になります。実際、コメンタリだけでは解析は難しく、黒本がなければかなりコードリーディングは難航していたと思います。

2021-04-16 02:48:31
ほえほえ@スプシマン @hoehoe1234

Unix V6のコードは ①Lionsコメンタリ ②はじめてのOSコードリーディング ③pdp11-40 processor handbook と、追加で④souce_with_linno_v6があれば読み解いていくことができると思います。皆さんもご興味あればぜひ購入してみてください。③と④はネットで公開されていますのでダウンロードできます。

2021-04-16 02:51:55
ほえほえ@スプシマン @hoehoe1234

callerがcalleeを呼び出す箇所はここになります。pdp11のC言語では関数呼び出しにJSR PC形式を使っていることが分かります。 pic.twitter.com/EIlbPOyDUL

2021-04-16 02:55:54
拡大
ほえほえ@スプシマン @hoehoe1234

calleeの先頭に制御が移った時のレジスタとスタックの内容です。 BP 変更なし SP 1ワード減る(下位に) PC calleeの先頭アドレス スタック 図の通り。戻りアドレスはアセンブラコードでいうと31行になります(JSRの次の行)。 pic.twitter.com/I7Jncvycch

2021-04-16 02:59:15
拡大
ほえほえ@スプシマン @hoehoe1234

図黄色がcallerから積み上げていったスタック、左水色が黄色からの続き(上に続くイメージ)です。「CSVがなにをやっているか?」というと「R2~R4」のレジスタのセーブなんですね。C言語側でローカル変数にレジスタ変数を使うためだと思われます。 pic.twitter.com/fUN3B93aG6

2021-04-16 03:13:48
拡大
ほえほえ@スプシマン @hoehoe1234

詳細は書けませんが、この関数(csv)は、コンパイラにより挿入(されるらしい)され、関数の最初で呼び出されます。ここでJSR R5, csv形式が使用されています。 pic.twitter.com/U0X9cAXr1K

2021-04-16 03:18:53
拡大
ほえほえ@スプシマン @hoehoe1234

CSVのコードはこちらとなります。JSR R5形式で呼ばれたにもかかわらず、CSVから戻るときにはなんとJSR PC形式を使用しています。これで何が起こるか?ということです。 pic.twitter.com/l7iPBBqIZq

2021-04-16 03:20:52
拡大