「プログラムはなぜ動くのか」の読書感想文

この間会社の図書館で「プログラムはなぜ動くのか」を見つけたので読んでみました

プログラムはなぜ動くのかの表紙

https://www.amazon.co.jp/dp/B00HRN7VK0

なぜこのチョイス?

以前どなたかのブログで

「最近はコードはかけるが裏側で何が起こってるのかわかってないやつが多すぎる」

みたいなことを言ってる人がいて、そこで紹介されてた覚えがありました

この主張に関しては思うところもあるんですが低レイヤーを知っていること自体はエンジニアにとってプラスだと思ったので

全体感想

内容としては応用情報で勉強したのとほぼ一緒

CPUとは、レジスタとは、2進数とは、メモリとディスクとはといった話がコンピュータ上でダブルクリックをしてから実際にプログラムが動作するまで実際には何が起こっているのかという流れで進んでいく

一つ一つの章は細かく丁寧に解説されてると思う

話が進んでいくのも個人的にはわかりやすかった

ただ、10章アセンブリ言語を読んでプログラムの動きを理解しようという部分で

筆者は「アセンブリ言語を経験していないプログラマは、自動車の運転方法だけを知っていて、その仕組みを知らない運転手に相当します。」と書いていたが

それはいろいろと違うだろ、とツッコミたくなった

概要

章ごとに短くまとめていきます

第1章 プログラマにとってCPUとは何か

CPUとはマシン語になったプログラムを実行する装置

CPUはレジスタ、制御装置、演算装置、クロックの4つの要素から構成される

レジスタはデータを格納する領域

制御装置は命令に応じてコンピュータ全体は制御する

演算装置はレジスタのデータを演算する

クロックはCPUが動作するタイミングとなるクロック信号を発生させる

第2章 データを2進数でイメージしよう

コンピュータはIC (集積回路)と呼ばれる電子部品で構成される

ICの中には数本から数百本のピンが並んでいるが、一つ一つのピンは0Vか +5Vの二つの状態しか持てない

なのでコンピュータで情報を取り扱うには1と0だけで表現する2進数で取り扱う必要がある

第3章 コンピュータが小数点数の計算を間違える理由

コンピュータはデータを2進数で表すので、数値を表現する場合には「2のN乗」を足して表現する

これは小数点数を表す場合も同じ

ただ、2のN乗の組み合わせは整数は全て表現できるが小数はうまくいかないことがある

具体的には2の-N乗をどれだけ足しても0.1を表現することはできず、循環小数になってしまう

なのでコンピュータ上で0.1となっている数は正確には0.1ではなく、10倍しても1にならない場合がある (10.000002とか)

これを回避するためには計算時には整数として扱い、計算が終わった後で割るという方法がある

第4章 四角いメモリーを丸く使う

モリーとはディスクから読み出したデータを置いておく領域

CPUがディスクから直接データを読み出すのには時間がかかるがメモリからは高速に読み出すことができる

メモリは論理的なイメージはビルのような構造で、各フロアに1byteのデータを保存するようにして使う

第5章 メモリーとディスクの親密な関係

モリーとディスクはどちらもデータを保存しておく記憶装置

それぞれに異なった性質があり、お互いの特徴を活かす形でコンピュータは動いている

  1. ディスクキャッシュ

メモリの一部にはディスクキャッシュと呼ばれる領域がある

ここには一度ディスクから読み出されたデータを保存しておく

一度読み出されたデータは何度か必要となることが多いので、それをメモリに保存しておくことで毎回ディスクから読み出すことによる時間のロスを減らしている

  1. 仮想記憶

仮想記憶とはディスクの一部を仮想的な記憶装置として利用する方法

ただ、実際にはメモリが増えているわけではない

ディスク内に仮想メモリー用の領域を用意しておき、実行されるプログラムを一定の大きさのページに分割しておく

そして必要に応じてメモリー仮想メモリーのデータの入れ替えを行う

第6章 自分でデータを圧縮してみよう

データの圧縮を行う方法は以下のようなものがある

  1. ランレングス法

同じデータを表すときに繰り返す回数をデータとしてもつことで容量を減らす方法

ex. AAABCCCCDD => A3B1C4D2

ただ実際の文書ファイルなどでは同じ文字が繰り返し出現することはそこまで多くなく、1文字を表現するのに文字 + 繰り返し数のセットが必要なランレングス法ではデータが圧縮前より大きくなってしまうこともある

  1. ハフマン法

データを出現頻度順に並べて、出現頻度の多いものを少ないbit数で表すようにする方法

ハフマン法で圧縮するとハフマン符号と呼ばれる対応表を圧縮後データが作成される

第7章 プログラムはどんな環境で動くのか

Wisdowsでは自分で書いたプログラムでハードウェアを直接操作することは基本的にはしない

OSを介してハードウェアを動かすことになる

OS + ハードウェアのセットのことを動作環境と呼ぶ

第8章 ソース・ファイルから実行可能ファイルができるまで

なんらかのプログラミング言語で記述したプログラムをソースコードと呼び、そのファイルをソースファイルと呼ぶ

CPUは機械語 = ネイティブコードしか理解できないので、翻訳をする必要がある

その翻訳をするのがコンパイラと呼ばれるプログラム

CPUごとに扱うネイティブコードが違うため、コンパイラはCPUによって異なる

コンパイルを行うとオブジェクトファイルが得られる

ライブラリなどを使用しているとオブジェクトファイル単体では処理が揃わず実行することができない

複数のオブジェクトファイルを結合することでexeファイルができる

第9章 OSとアプリケーションの関係

OSは制御プログラム、言語プロセッサ、ユーティリティなど複数のプログラムの集合体

OSが存在する以上ハードウェアを直接操作するようなプログラムを書くことはなく、OSの機能を利用しているということを意識しながらプログラムを書くことが大切

OSのハードウェア制御機能は小さな関数の集合体として提供されているのが一般的

これらの関数、及び関数を呼び出す行為をシステムコールと呼ぶ

Cなどの高水準言語は特定のOSに依存しない

高水準言語では独自の関数名を使い、それをコンパイル時に該当するOSのシステムコールに変換する

このようにOSと高水準言語によりハードウェアを抽象化することができる

第10章 アセンブリ言語からプログラムの本当の姿を知る

アセンブリ言語とはネイティブコードと一対一に対応する言語

なのでネイティブコード => アセンブリ言語への変換を行うことができ、アセンブリ言語を読むことができるとプログラムの実行される様子がわかるようになる

この章では実際にアセンブリ言語を見ながらプログラムが実行される順番などを解説していた

第11章 ハードウェアを制御する方法

Windowsを例にとり、OSがハードウェアを制御する方法を解説する章

ハードウェアの制御にはIN命令とOUT命令を使う

IN命令では指定した番号のポートからデータを入力しレジスタに格納する

OUT命令ではレジスタに格納されているデータをしてしたポート番号に出力する

また、コンピューターでは文字入力などリアルタイムに処理を行うことが求められる

これらは割り込み処理を使って実現されている

割り込み処理とは名前の通り現在実行中のプログラムの処理を途中で止め、他のプログラムの実行に処理を移す仕組み

第12章 コンピュータに考えさせるには

人の思考をプログラムで表すには処理として記述する方法がある

この章ではジャンケンのプログラムを作って、さらに過去の対戦結果を記憶させておいてプログラムに思考させるというのをやっていた