概要

去年の11月頃からやってたtwitterで知り合った知らない人にプログラムを教える企画のC言語編である「暇つぶしプログラム教室 C言語編」が、無事完成した。 一人目が最後まで終わったので、特に実現不可能な部分とかは無いはず。

内容

全三回となった。

  • 第一回 簡易PostScriptに独自拡張を入れたインタープリタを作り、それをVM化する
  • 第二回 QEMUのOS無しARMで、ARMのアセンブリや実行バイナリを学び、簡易ディスアセンブラと簡易アセンブラを作る
  • 第三回 アセンブリの知識をもとにリンクやtext, data, bss、ロードなどの知識やCの関数がアセンブリとしてはどう見えるのかなどを見る(最後におまけとしてインタープリタのJITをやる)

第二回までは課題があって、それをこなして私がレビューする、という形式です。 第三回は課題はちょっとしか無くて、だいたい自分で調べるだけの内容になっています(おまけ除く)。

だいたい各回、集中してやれば一週間くらいでやれる分量と思っているけれど、実績を見ると3週間くらいが多いですかね? 第一回と第二回は2000行くらいのコードを書く事になる。

C言語の入門書を終えた所から、OSやコンパイラなどの専門書を読み始める所までの間のギャップを埋める事を狙いとしていて、だいたい埋められた気はしている。 objdumpやnmなどのbinutilsをそれなりに理解して、いろいろ試行錯誤する経験などが積めるように配慮した。

作る側として意識した事

内容自体は実物を見てもらう方が良いとして、ここでは作る時に考えた事などを書いておく。

まずC言語を教えてほしい、と言われて始めた事なので、なるべくC言語を学ぶメリットが得られるように考えた。 またC言語の面白さのエッセンスがなるべく詰め込めるような内容を考えた。 面白さは結構大切な所だと思う。「おぉ、これがC言語か。すごいな!」と思えるような物を目指した。

C言語はオブジェクトファイルというものがC言語とは独立してある所が特徴と思う。 だからそうしたC言語の周辺の事も、環境をQEMUに固定して積極的に解説していった。 プラットフォーム非依存な物を作るよりは、プラットフォームを学ぶ題材くらいの姿勢で。 プラットフォームを学ぶ面白さみたいな物もそれなりに詰められたと思う。

また、プログラムの入門書を読んだあとに、実際に手を動かしていろいろ学ぶ機会が必要と思っているので、そういう機会を用意する、というのを目指していた。 写経じゃなくて、ちゃんとバグを生んで、それを追って、理解する。 リンクエラーなども起きて、定義の順番とかヘッダファイルをがちゃがちゃしてみる機会を与えるのを目指した。 この辺は適当に経験を積んでいけばそのうちやる訳だけど、それでは大量の経験が必要になる。 もうちょっと必要な事だけを詰め込んだ箱庭みたいな所でやれないかなぁ、というのが意図としてある。

実際に試す環境として、UbuntuとQEMUを決め打ちしているのも意識した所。 QEMUのクロス環境周りはすぐに手順が変わるので、2018年11月時点での最新のやり方をちゃんと全部載せる、というのは目指した事。 数年後にはここの内容も古くなるとは思うけれど、ある時点で揃っている方が古くなったあとも使いやすいと思うので、現時点ですべて動くコマンド例を提供するのは意識した。

あと、わからないけどなんか動いてしまうすごい事、というのはなるべく廃するようにした。 あくまで勉強目的として、すごい物を作るよりもちゃんと理解出来る事を目指して、 地味だけど難しい事にちゃんと時間をかけようとした。 結果として、やった人は多くを学んだと思うけれど、それをあまり他人にわかりやすくは伝えられない気がする。端的に言えばバズらなさそう…

勉強目的と割り切る事も重視した。 「あとはこれと同じ事をひたすら揃えればOK」という所まで行ったら、それ以上はやらない。 それをやれば派手な結果になるのだけど、やっても学ぶ事はどうせ無いので。 何か実用的な物を作っているフリをするのでは無く、 勉強目的としてもっとも効果が高い物を作るというのを目指した。 結局本当に本格的にやる時はLLVMやDalvikVMなどをちゃんと勉強する事になるので、 本格的に見えるハリボテを作るよりは、本物を勉強する時の土台を築く事を目指した。

内容に派手さが無いのはデメリットとは思うけれど、その代わりに、内容の高度さの割には易しいと感じると思うし、多くを含められたと思う。 bssとdataの違いとかnmやreadelfでリンク周りの問題を追えるようになる、 とかは、作る物よりも教育的な内容を重視したからこそここまで含められたと思っている。

必要な難しさを隠さない事と、不要に難しい事を含めないのも意識した。 プログラムを学ぶ上で必要となる割と膨大な周辺知識は隠さないようにした。 けれど、実際は知らなくていいよな、という事を並べて威圧するような事は避けて、必要だと思える物に絞る事も意識した。

最後のJITのおまけだけは少し不要に難しいと思うが、それ以外の内容はどれも「まぁこのくらいは必要だよね」とちゃんとベテランが同意出来る物だけに絞ったつもり。

あとは課題自体で終わるのでは無く、これを終えたあとにC言語やプログラムを続けていいく上でなるべく役に立つ物を目指した。 これは自分の過去のプログラム経験と、最近自分が出会ったプログラム周りのトピックを意識している。 特に最近のトピックを意識して内容を選んでいるのは珍しいと思う。

この辺は実際に終えた人がその後プログラマ人生を歩んでいってしばらく経ったあとにしか評価出来ない所と思うので、うまく行ったかどうかはその時にも聞かせてもらいたい所。

なかなか良いコンテンツが出来た

ちょうと昨日、一人目の人が最後のJITの課題を終えて、一通りフィードバックも反映しおえた。 少なくとも一人が終えられたので、コンテンツとして必要な物は一通り揃ったと言えそう。 結構な分量と期間でやってきたので、無事終わって謎の達成感がある。

だいたい最初に始めた時点でも作ってる側としてはこのくらいの分量を想定出来ていたので、 受ける側は途中で挫折しちゃうかもなぁ、と思っていた。 だから無事最後まで完走出来て、おぉ、大したもんだな、とか思っている。 このくらいの量になるとそれなりの期間が必要になってしまうので、私生活が忙しくなったりとかいろいろあって途中でやめてしまうのも多いだろうから。

このくらいの分量の何かを書くのは、一人でやってると挫折しがち。 だからやる人が居ると張り合いがあっていいね。 今後もまた何かこのくらいの分量の物を書いていきたいなぁ。

過去の関連エントリ