しかくいさんかく

解答略のメモ

1日目: 方針

この記事はひとりでCPUとエミュレータとコンパイラを作る Advent Calendar 2017の1日目の記事です。

自己紹介

はじめまして。都内のIT屋で働いている解答略という者です。

去年の冬まで物理系の大学院博士課程に在籍していて、情報系とは無縁でした。 大学を離れる間際に、何の知識も無いままIT業界に入ると怖い人に怖い事を言われると思い、情報科学科の後輩を訪ねたところ「低レイヤを知れ」というアドバイスをもらい、 大急ぎでエミュレータコンパイラとCPUを作りました。

時系列で振り返ると

大急ぎで作ったのでマジでくそしょぼいやつしかできませんでしたが、「PCの動作原理の雰囲気は掴んだ」という実感がわいたので、まぁええかと思いました。

作る前は、、、フリップフロップ、マルチプレクサ、キャリーフラグ、HDL、RTL、FPGAニーモニックオペランドBNF、抽象構文木、シンボルテーブル、スタックマシンなどの単語は聞いたことすらありませんでした。 そんな有様から出発したわけですが、一ヶ月ぐらいでなんとかなるものです。 低レイヤに関する知識を持たない読者の方も、敬遠する必要は無いと思います。 原理原則だけであれば、想像よりはるかに簡単だと思います。

本題

このAdvent Calendarの目標はただ一つ、目の前のPCがどのように動いてるのか理解することです。

しかし現代のPCは極度に複雑なシステムで、全てを完全に理解するのは多分不可能です。 そこで今回はCPUの挙動にフォーカスし、電子回路からC言語に至る一本の道筋を提示しようと思います。 言い換えると、普段目にする抽象的なプログラムコードから、CPU内の電圧変動が想像できるようになりたい。 こうした能力を身につければ、PCの仕組みを(なんとなく)理解した(ような雰囲気になれる)と思います。

一年前の僕はそんなことを考えながら、せっせと低レイヤの環境を自作していました。 あれから日が経って知識を忘れつつあるので、今のうちに当時のメモを再編集して公開しようと思いました1。 今後の予定をざっくり書くと

第一週目:回路素子とCPU
第二週目:x86
第三週目:コンパイラ
  • 字句解析
  • 解析木
  • 抽象構文木
  • シンボルテーブル
  • コード生成
第四週目:完動

抽象化の階段を一歩づつ登る形式です。 順序は大きく変わらないと思いますが、各パートの分量が未知数なので予定通りに進むかは微妙です。 ただ、頓挫することだけはないように頑張りたいと思います。

我々の敵

なにぶん初心者なので、難しいことは手を出さないようにしていました。 しかし教科書読んで終わりというのも違う気がしたので、以下の点に気をつけていました。

敵1: 概論

高校や大学教養学部の情報の授業は「メモリーは机だよ~」的なフワフワした概論に終始し、嫌悪感を覚えていました。 そこで、全部自分で作れば必然的に全ての概念と向き合うことになると思い、何でもかんでも自作しようと考えました。 そして完成品の質が低かったとしても、とりあえず動くという結果だけは譲らないことにしました。 概論だけで終わらないようにします。

敵2: 最適化

PCの動作原理を理解するのが目的なので、基本に忠実にいきたいと思います。 なので最適化は後回しです。 つまり実行効率が悪かろうととりあえず動けば勝ちの精神でいきます。 最適化は理解の敵だと思っています。

敵3: x86から逃げる

ひとくちにCPUと言っても沢山の種類あるのですが、僕達が普段使うパソコンにはx86というタイプのCPUが入っています。 x86の仕様はややこしい(らしい)のですが、しかし今回はCPUからエミュレータからコンパイラまで、全てをx86ベースで製作することにしました。 理由は、他のCPUをベースにすると目の前のPCを理解した気にはなれないと思ったからです。 x86を基軸にすれば、自作しながら普段使ってる環境がどうなってるのか学べるので面白いと思います。

敵4: 完成度の向上

例えばx86の命令セットを完全にカバーするような不毛な作業はしません。最低限の命令だけを雑に実装します。 上位レイヤーのコンパイラ氏にとって不都合がなければ、それでOK。 機能も完成度も貧弱ですが、その代わりCPU、エミュレータコンパイラの全てが協調して動くことに全神経を注ぎたいと思います。

敵5: 周辺機器

IO周り(つまりマウスやキーボード)の取扱いがひどい(というか、ほぼない)ので、気になる方が多いと思います。 ブート処理についても首を傾げる方が多いと思います。

偏った意見で恐縮ですが、PCの動作原理を理解するためには、まずCPUとメモリだけからなる系を考えるのが良いと僕は思うのです。 周辺機器の割込処理やブート処理については、その後OSを自作することで身につけるのが良いと思っています。 そういう思想に毒された人間ですので、周辺機器の扱いについては「仮想メモリにうまいことマップされる」程度でお茶を濁しています。

その他諸々

重要なことですが、初心者が適当に書く記事なので誤った内容が多々あると思います。ミスだらけの前提で読んでください。 尚、僕がミスに気づいた場合には面倒くさいので注釈とかいれずに勝手に直すことを了承下さい2はてブtwitterでミスを指摘していただいたら、記事の最下段で言及すると思います(時間があれば)。

特に専門用語に関してですが、「とりあえず動く」という状況を達成する上で用語の厳密な定義はほとんど必要なかったので、使い分けの不適切な箇所が多々あると思います。 例えばCPUとMPUとコアとプロセッサの違いとか、シミュレータとエミュレータとデバッガの違いとか、ラッチとフリップフロップの違いとか、僕は全然知りません。 変なことを書いてたら遠慮なく指摘して下さい。直しますので。

また昔の自分に言い聞かせるつもりで書くので、随所に失礼な表現があり読者を腹立たせるかもしれません。 明日からは敬語じゃなくて「OOはXXだ。」みたいな文章を書くと思います。 私的なメモ帳をのぞき見るつもりで読んでいただければ幸いです。

それでは、明日から23日間よろしくおねがいします。


  1. アドベントカレンダーに登録すれば、怠惰な自分でも復習するだろうと思って登録したら、予想外にバズってビビりました

  2. 正確な情報が欲しい人は、こんな個人的なメモではなくちゃんとした教科書を読むべきです。ブログをあてにしてはいけません。