手を動かして実装しながら『コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方』を読んだ(前半)
コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方
最初は効率優先で内容だけ理解しようと3章まで読み進めたが、 理解が前提となっている各章末の実装部分を飛ばしている事で、徐々にしっくり来ない違和感が増えてきてしまった。
それに、まえがきにもこう書いてある。
コンピュータはどのように動いているのか? それを理解するための最善の方法は、コンピュータをゼロから作り上げることである。筆者らはそのように信じて疑わない。 その考えに則り、考案したプランは次のようになる。まず、単純ではあるが十分にパワフルなコンピュータシステムを明確に規程するところから始める。 そして、そのプラットフォームとなるハードウェアと階層構造からなるソフトウェアをゼロから作り上げていくのである。 ここで「ゼロから作る」という言葉を用いたが、これは、基本要素として使えるパーツは論理ゲートだけであるということを意味する。 つまり、論理ゲートだけを用いてコンピュータの構築を行うという計画である。
なので、そもそも手を動かして「作る」という事を行わないと、本の意図ともずれてしまう。 そこで私は、主に欧米の大学でコンピュータサイエンスの教科書として使用されてきたこの本にしっかりと向き合おうと決めた。 ここからはコロナ禍で取り組むにあたって読んだ本を「準備編」として紹介し、 それから各章の内容を記していく。
準備編
コロナの影響で在宅・リモートワークが当たり前となり、急に人間の自律性がより強く求められる世の中になった。 出社という強制的なイベントが減り、往復の通勤時間がなくなり自由な時間が増えた。 活かせるかどうかはその人次第。という事で行動様式を見直す/学ぶ良い機会と捉え、以下の書籍を読んだ。
作業療法士の方が書かれた本で、脳機能の観点から行動を変える方法が書いてある。 →この本を読み、家でのタスク等すぐに取りかかる事が圧倒的に増えたので効果に驚いている。
習慣のメリットや習慣でどう人生が変わるかというエピソードが書かれており、習慣形成のコツが得られる。
個人的にはこれが1番オススメで、
- モチベーションに頼るのはどうして上手くいかないのか
- 大きな目標を前にすると、なぜ意志の力が消耗するのか
といった事が書かれており、共感する点が多かった。
これらの本を読み、
- 毎日少しずつでもいいから進める
- 「理解」を重視し時間をかける
- 実装部分は基本自分で考えて解く
(本を読み理解している文法では解けない/時間がかかる場合のみ調べる事にした)
というルールを設定し、1章から再スタートした。
1章 ブール論理
あまりに単純なものから、人間が手に負えないほど複雑なものが作られる。 - アメリカの詩人 ジョン・アッシュベリー
この本には様々なシミュレーターが提供されているので、 実際に「作る」と言っても、はんだごてを使ったり部品を用意する必要はない。 コンピュータ上でハードウェア記述言語(HDL)を用いて、回路のアーキテクチャを設計し、最適化について考えることができる。
出発点はNandゲートであり、このNandゲートから他のすべてのゲートと回路が作られる。 このゲートは基本要素として使うため、実装する必要はなかった。
実装した論理ゲート
- Not
- And
- Or
- Xor
- マルチプレクサ(Mux)
- デマルチプレクサ(DMux)
- 多ビットNot/And/Orゲート
- 多ビットマルチプレクサ
ここらへんはまだ簡単というか、ロジックも単純であり、 普段プログミングに出てくるいわゆる Not(!)やAnd(&&)を実装していて楽しかった。
効率の点で言えば、一般的な指標は「do more with less」 つまり「ゲートの数をできるかぎり減らせ」ということになる。 ゲートの仕様(インターフェース)が与えられたとき、 すでに実装済みの他のゲートを用いて対象のゲートを実装する効率的な方法を探す、ということである。
2章 ブール算術
本章では、数を表現し算術演算を行うための論理ゲートを作成する。 コンピュータで行われる算術演算と論理演算はすべて、このALU回路によって行われる。 そのため、ALUの機能を理解することは、CPU、さらにはコンピュータ全値の仕組みを理する上で重要なステップとなる。 2真数の加算は単純な演算であるが、奥が深い。 驚くべきことに、デジタルコンピュータによって行われる命令の多くが「2進数の加算」へと還元することができる。 そのため、コンピュータの多種多様な命令を実装するにあたって、2進数の加算を理解することが重要である。
実装した回路
- Inc16(加算器):与えられた数字に1を加算できる回路
- Add16(加算器):2つの16ビットの和を求める
- HalfAdder(半加算器):ふたつのビットの和を求める
- FullAdder(全加算器):3つのビットの和を求める
- ALU(算術論理演算器):Hackと呼ばれる特定のコンピュータプラットフォームで使われる専用の回路
ほとんどが入力の数も限られており実装も単純だったが、 ALUは入力も8つ、出力も3つあり、仕様を見るだけでも組み合わせが多く、大変だった。 コードは整理すればもっと短く書けるとも感じるが、1つずつコツコツ組み合わせていった。
2の補数 2進コードにおいて符号付き整数を表現するため、これまでいくつかのコード体系が考案されてきた。 今日ほとんどすべてのコンピュータで用いられる方式は、2の補数と呼ばれる方式である。
3章 順序回路
1章と2章で構築した論理演算や算術演算の回路はすべて、組み合わせ回路と呼ばれる。 組み合わせ回路は、入力値の組み合わせだけによって、関数の値が決定する。 このどちらかと言えば単純な回路は重要な処理をたくさん行うことができるが、 状態を保つことはできない。 コンピュータは値を計算するだけでなく、その値を保存し呼び出すことができなければならない。 そのため、時間が経過してもデータを記憶することのできる記憶素子を備える必要がある。 この記憶素子は順序回路から構築することができる。
Go言語に取り組んでから、知りたいという好奇心が強くなっていると感じている。
やはりドキュメントを読んでも挙動が分からない時など、ライブラリの中身などを型に制御されながら追っていくので理解が深まる経験を多くする。
メモリは、机の上に例えられたり一時的に記憶できる装置と言われる事もあるが、(最初のとっかかりとしては良)
そういった表面上で捉えるための説明ではなく、一体どう構成されていてどう動いているのかちゃんと理解したいと感じるようになってきた。
この章はそんな欲求に応えるのにぴったりで、
クロック→フリップフロップ→レジスタ→メモリと全ての説明が連結していく。
より下位レベルの抽象化から、より複雑なものへとボトムアップ的な視点で捉える本書のアプローチをまさしく感じる章になっている。
実装した回路
4章 機械語
何事もできるかぎりシンプルにすべきだ。だが、シンプルにしすぎてはいけない。 - アルベルト・アインシュタイン
コンピュータを構造的な視点から説明するには、そのハードウェアプラットフォームを定時し、 それが下位レベルの回路からどのように構築されているかを説明すればよい。 また、コンピュータを抽象的な視点から説明するには、その機械語の仕様を示し、 その機械語によって何ができるかを明らかにすればよい。 実際のところ、新しいコンピュータシステムに慣れ親しむためには、開会後で書かれた低水準言語のプログラムを最初にいくつか見るのが手っ取り早い。 これは、コンピュータに何か有用なことを実行させる方法を理解するだけではなく、ハードウェアなぜそのように設計されているかを理解するためにも役立つ。 その点を考慮して、本章では機械語による低水準のプログラミングに焦点を当てる。
Hack機械語の仕様 概要 Hackコンピュータはノイマン型のプラットフォームである。 それは16ビットのマシンであり、CPU、メモリモジュール、メモリマップドI/Oデバイスを備える。 メモリモジュールには命令用とデータ用のメモリが離れた場所に存在する。 メモリマップドI/Oデバイスじゃスクリーン用とキーボード用のふたつがある。
実装したプログラム
- 乗算プログラム
- 入出力操作プログラム
アセンブリプログラムを書き、本書で提供されているアセンブラで機械語に変換し、CPUエミュレータを用いて、実行/テストを行う。
5章 コンピュータアーキテクチャ
本章は"ハードウェアの旅路"における頂きである。 ついに、1~3章までに作成した回路を使って、汎用コンピュータを作る準備が整った。 この汎用コンピュータは、メモリに格納された機械語プログラムを実行することができる。 我々が作ろうとしているコンピュータ-このコンピュータはHackと呼ばれる-は、ふたつの重要な性質を持つ。 まずひとつに、Hackはシンプルなマシンであると言える。 これまでに構築した回路と本書が提供するハードウェアシミュレータを用いれば、ものの数時間で作ることができる。 また、その一方で、Hackは十分にパワフルなマシンであり、デジタルコンピュータの主要な動作原理とハードウェア要素を兼ね備えている。 そのため、Hackを作ることで、「現代のコンピュータがどのように動作しているのか」ということについて、 ハードウェアとソフトウェアの低レイヤのレベルで理解することができるだろう。
ノイマン型コンピュータは実用的なアーキテクチャである。 今日のコンピュータプラットフォームはほとんどすべて、このノイマン型コンピュータと概念上の枠組みは同じである。 ノイマン型アーキテクチャは中央演算装置を中心として、メモリデバイスを操作し、入力デバイスからデータを受け取り、 出力デバイスへデータを送信する。 このアーキテクチャの心臓部は「プログラム内臓」という方式にある。
構築した内容
- Memory
- CPU
- Computer
この本は単なる架空のコンピュータを作らされるわけではなく、現実に即しているため実用的な点が良い。
またプリミティブな要素として基本部分はブラックボックスとして提供されるが、
それを除けば、これまでの章が全て土台となり積み重なって曖昧な所がなく構築できるため、理解度も深い。
6章からはどれかプログラミング言語を選択して実装していく部分もあるため、Go言語を用い取り組んでいきたい。 後半に続く。