コンピューターシステムの理論と実装 とは?
コンピュータシステムをゼロから作って学ぶベストセラー書の改訂第2版。コンピュータを理解するための最善の方法はゼロからコンピュータを作ることです。コンピュータの構成要素は、ハードウェア、ソフトウェア、コンパイラ、OSに大別できます。本書では、これらコンピュータの構成要素をひとつずつ組み立てます。具体的には、NANDという電子素子からスタートし、論理ゲート、加算器、CPUを設計します。そして、アセンブラ、仮想マシン、コンパイラ、OSなどを実装しコンピュータを完成させて、最後にその上でアプリケーション(テトリスなど)を動作させます。
とのことで去年の10月くらい?に改訂版が出て、面白そうなので買ってみましたが1年間の間机に積まれていました。
それを冬休みの間に少しずつ進めて前半の論理ゲート→加算器→CPU→アセンブラのハードウェア作成パートを完了したので感想を書きます。
ちょっと興味はあるけど、特にコンピューターサイエンスの知識もないまま開始しているので、同じように興味のある方の参考になれば幸いです。
進めやすさとテスト
論理ゲートからCPUを作ると言ったってはんだごてとかがないとできないんじゃないの?と思ってました。心配ないです。ハードウェア記述言語(HDL)という言語があり、それを使うとプログラムとしてチップを作成することができます。
それから、各章ごとにこれから作るものの全体像が示されて、詳細の設計が与えられ、Web上で使えるIDEと作ったプログラムが正しいかを確認するためのテストが用意されているので思っているよりもかなり進めやすいと感じました。
正解しているとsuccessfulとか出ます。
感想
AndとかNandとかOrとかの論理チップを組み合わせて加算器とかALUと呼ばれるものを作ったりするのだけど、その辺りはパズルみたいでとても楽しかった。
プログラムを書くようにifで場合分けして。。。
みたいな段階的に処理していこうという考えはあまり使えなくて、どの値が入ってきても一発で最終的な出力があってないといけないんだ。と気づいてノートに表を書いてみたり、チップの回路を書いてみたりしてパズルを解くような感じだった。
その後作ったものを組み合わせてCPUを作ったが、ちょっと難しかったので他の人の記事を参考にしたりした。
アセンブラの章は結構楽しくて、好きな言語で文字列操作とかするプログラムを作っていきます。機械が読める記号(どこどこのメモリを読み出して+1した結果をそこに書いてみたいな命令たち)をバイナリに変換するというプログラムです。
Assembler.py
# Assembler.py
import sys
from Parse import Parser
from Code import Code
from SymbolTable import SymbolTable
class Assembler:
def __init__(self, filename):
self.filename = filename
self.parser = Parser(filename)
self.code = Code()
self.symbol_t = SymbolTable()
self.output_filename = filename.replace(".asm", ".hack")
self.output_file = open(self.output_filename, "w")
self.next_var_addr = 16 # 次のRAMアドレス
# A命令をバイナリに変換
def aInstruction(self, symbol):
if symbol.isdigit():
return "0" + bin(int(symbol))[2:].zfill(15)
else:
if self.symbol_t.contains(symbol):
addr = self.symbol_t.getAddress(symbol)
else:
self.symbol_t.addEntry(symbol, self.next_var_addr)
addr = self.next_var_addr
self.next_var_addr += 1
return "0" + bin(addr)[2:].zfill(15)
def assemble(self):
# 1パス
rom_addr = 0
while self.parser.hasMoreLines():
self.parser.advance()
t = self.parser.instructionType()
if t == "L_INSTRUCTION":
self.symbol_t.addEntry(self.parser.symbol(), rom_addr)
else:
rom_addr += 1
# 2パス
output_lines = []
self.parser = Parser(self.filename)
while self.parser.
6章までの前半パートを終わらせるのにかかった時間は25時間くらいでした。
後半もやり切れたらまた感想を書きます!
