こんにちは。
プログラムはなぜ動くのか 第2版を読み終わったので内容を忘れないように学んだことを要約したメモを載せます。
このエントリは完全な個人のメモです。
自分のお勉強のためにこの本を読んだので、内容を覚えるためにSummarizing(サマライジング)を行います。
1章~4章の要約はこちら
5章~8章の要約はこちら
ここから9章以降の内容です。
9章 OSとアプリケーションの関係
モニター・プログラム
OSが無かった時代はプログラマは全ての処理を機械語で書き、それをスイッチによって入力してマシンを動かしていた。
それだとプログラムを動かすのに果てしない労力を要するので、プログラムのロードと実行だけを行うプログラム(モニター・プログラム)が作られた。
その後、モニター・プログラムにハードウェア制御や言語プロセッサ(アセンブラやコンパイラ、インタプリタのこと)などの様々なユーティリティが追加された。
これが現在のOSの原型。
これができたことにより、プログラムを作るのはかなり楽になった。
システム・コール
ハードウェア制御機能は関数の集合体で提供されているのが一般的。
これらの関数や、関数を呼び出すことをシステム・コールという。
システム・コールがあるおかげで、プログラマは直接ハードウェア制御をするコードを書かなくてよくなった。
さらに、C言語などの高水準言語では標準関数の中でシステム・コールが行われているので、高水準言語ではシステム・コールも意識しなくてよくなった。
直接プログラムからシステム・コールできる言語もあるが、プログラムの移植性が低くなってしまうので基本的には非推奨。
Windows OSの特長
・32bitまたは64bit OSである
32bit, 64bitとはそのOSが最も効率的に処理できるデータのサイズ。
・APIという関数セットでシステム・コールを提供する
プログラマはシステム・コールを使うことで直接ハードウェア制御を記載する必要がなくなる。
Windowsのシステム・コールはC言語で書かれている。
・GUIを提供する
画面とマウスによる操作が可能。
文字だけの画面をCUIという。
・WYSIWYGによる出力ができる
ディスプレイに表示されているものをそのまま印刷できることをWYSIWYGという。
What You See Is What You Getの略。
・マルチタスク機能を提供する
マルチタスクとは、複数のプログラムを同時に実行できる機能のこと。
1つのプログラムの中の独立した機能を同時に実行するマルチスレッド機能も提供している。
・ネットワーク機能やデータベース機能を提供する
ネットワーク機能やデータベース機能のことをまとめてミドルウェアということもある。
OSとミドルウェアをまとめてシステムソフトウェアと呼ぶこともあるらしい。
・プラグ&プレイによるデバイス・ドライバの自動設定を提供する
新しい装置を接続したらすぐに使える機能。
新しい装置を接続するとデバイス・ドライバのインストールと設定が自動で行われる。
10章 アセンブリ言語からプログラムの本当の姿を知る
アセンブリ言語と機械語
CPUが処理できるのは機械語で書かれた命令だけ。
しかし機械語は数字の羅列なので、人間にとっては非常に扱いづらい。
そこで機械語の命令に分かりやすい英語の略語を付けてわかりやすく命令を書けるようにしたのがアセンブリ言語。
この略語のことをニーモニックという。
アセンブリ言語で書かれたものは当然CPUは処理できないので、アセンブリ言語を機械語に変換する必要がある。
アセンブリ言語を機械語に変換をアセンブルといい、変換してくれるツールをアセンブラという。
また、機械語をアセンブリ言語に変換することも可能で、この場合は逆アセンブルという。
C言語などの高水準言語もコンパイルをすることによって機械語に変換される。
コンパイル時のオプションで高水準言語からアセンブリ言語に変換することも可能。
アセンブリ言語の構成
アセンブリ言語は機械語にそのまま変換される命令(オペコード)と命令の対象(オペランド)、アセンブラに対する命令(疑似命令)で構成される。
疑似命令はプログラムの構造やアセンブルの方法をアセンブラに指示するためのもの。
例えば、セグメントを区切る「segment」と「ends」や、複数のセグメントを1つのグループとしてめとめる「group」命令がこれにあたる。
オペコードはレジスタやメモリに値を格納する「mov」やスタックに値を格納、取り出しを行う「push」「pop」命令などのこと。
オペランドではレジスタなどを指定する。
関数呼び出しの仕組み
call命令で関数の先頭アドレスに処理の流れを移す。
call命令実行時、call命令を実行する下か所の次のアドレスが自動的にスタックにプッシュされるようになっている。
関数終了時、このアドレスがスタックからポップされて呼び出しもとに戻る。
関数呼び出し時の引数はスタックで渡され、戻り値はレジスタで返される。
グローバル変数とローカル変数の領域
グローバル変数の領域はプログラム開始時から確保され、プログラム実行中はどこからでも参照可能。
ローカル変数はスタックやレジスタを使って一時的に確保される。
レジスタに空きがあれば基本的にはレジスタを使う。
これはレジスタのほうが処理が早く行えるため。
繰り返しや分岐の実現方法
繰り返し処理は比較命令とジャンプ命令で実現する。
繰り返し回数とループカウンタを比較命令で比較し、ループカウンタが繰り返し回数に達するまで繰り返し処理の先頭までジャンプする。
比較命令の結果はフラグレジスタに格納される。
ただし、フラグレジスタの値はプログラムから直接参照することができないため、ジャンプ命令を使い分ける。
ジャンプ命令には
・jl(jimp on less than)命令
・jle(jump on less or equal)命令
・jge(jump on greater or equal)命令
・jmp(jump)命令
などがある。
jl命令は比較結果がより小さければ指定されたアドレスにジャンプ、jge命令は比較結果が等しいかより大きければ指定されたアドレスにジャンプ、jmp命令は比較結果によらずジャンプ(C言語でいうgotoみたいなもの)といった具合。
if文による分岐命令もこれらの命令を使って実現している。
11章 ハードウェアを制御する方法
高水準言語プログラムからハードウェアを制御する方法
OSが提供しているAPIを使う。
実際のハードウェアの制御OSが行う。
個々のAPIは関数になっていて、関数の実体はDLLファイルに格納されている。
IN命令とOUT命令
Windowsがハードウェアを制御するために使うのは入出力命令。
代表的な2つの入出力命令はIN命令とOUT命令。
IN命令とOUT命令はアセンブリ言語のニーモニックにあたる。
IN命令は指定されたポート番号からデータを取得しレジスタに格納し、OUT命令はCPUのレジスタにあるデータを指定されたポート番号に出力する。
ポート番号やポートとは
パソコンと周辺機器を接続するコネクタにはそれぞれI/OコントローラというICが接続されている。
ディスプレイやキーボードにはそれぞれ専用のI/Oコントローラがある。
このI/Oコントローラの中に一時的に入出力データを格納するためのメモリが存在し、そのメモリのことをポートという。
ポートのことをレジスタということもあるが、その場合はCPU内部にあるレジスタとは別の意味になるので注意。
それぞれのポートはポート番号で識別される。
このポート番号はI/Oアドレスと呼ばれることもある。
このI/OアドレスはWindowsの場合コントロールパネルから確認することが可能。
割込み要求
現在実行中のプログラムを一時中断し、他のプログラムを実行することを割込み処理という。
割込み処理を要求するのは周辺機器に接続されたI/Oコントローラで、割込み処理を行った周辺装置を特定するのには割込み番号を使う。
割込み番号に応じて実行される割込み処理はOSまたはBIOSが提供している。
割込み要求はI/Oコントローラが直接CPUに出すのではなく、割込みコントローラに出す。
割込みコントローラは複数の周辺装置から割込み要求を受け取り、割込み要求を受け取った順番や優先度を考慮しつつCPUに割込み要求を出す。
割込み処理では最初にCPUのレジスタにある値をすべてスタック領域に退避する。
これは割込み処理が終わった後に再度同じ状態でプログラムを再開させるため。
この仕組みをコンテキストスイッチという。
なぜ割込み処理が必要か
この割込み処理はハードウェアの制御において重要な役割を果たしている。
割込み処理があるおかげでキーボードやマウスの入力、ディスプレイへの出力がリアルタイムに行われる。
割込み処理を使わなくても周辺装置からデータの入力は可能だが、その場合常にメインプログラムの中で周辺装置の入力をポーリングしなければならない。
DMA
DMAとはDirect Memory Accessの略。
DMAはCPUを仲介させずに周辺装置が直接パソコンのメイン・メモリとデータ転送を行うこと。
ディスク装置などでよく利用される。
DMAを使うことで短時間で大量のデータをメイン・メモリに転送することができる。
ディスプレイ表示の仕組み
ディスプレイに表示される情報を記憶しているVRAMというメモリが存在する。
VRAMはVideo RAMの略。
プログラムでVRANの中身を書き換えればそれがそのままディスプレイに表示される。
VRAMを書き換えるためのプログラムはOSやBIOSで提供される。
現在のパソコンではビデオカードやグラフィックボードと呼ばれる専用のハードウェアにVRAMとGPUが装備されていることが多い。
GPUはGrapjics Processing Unitの略。
これはグラフィックを高速に描画するために多くのRAMと専用のプロセッサが必要なため。
12章 コンピュータに「考え」させるためには
人間の思考プロセスをプログラムで表現する
人工知能の話ではなく、じゃんけんゲームを作りながら人間の思考プロセスをプログラムに起こしていくという内容。
コンピュータは自分でものを考えることができないので、明確に指示を与える必要がある。
何も考えていない状態を表現する
何も考えてない思いつきなどは乱数を使って表現。
1~3の乱数を作ってそれぞれにグー、チョキ、パーを割り当てる。
人間の癖(グーを出すことが多い)なども乱数で表現。
例えば、1~10の乱数を作って1~5ならグー、5~7ならチョキ、8~10ならパーなど。
今まで相手が出してきた手を記憶して、次に出す手を考える
配列などで今までの手を保持しておき、最も出す確率が高い手に勝てる手を出すなど。
2次元配列を使ってグーのあとはチョキを出しやすいからグーを出すなど。
思考パターンをあらかじめ複数用意して、任意のタイミングで切り替える
グー、グー、チョキ、パー、チョキ、グー
パー、チョキ、チョキ、チョキ、グー、パー
を順番に出すパターンを用意しておいて、2回連続で負けたら別のパターンに切り替えるなど。
大体こんな感じです。
プログラムはなぜ動くのかはこれで終わりです。
思ったよりも知らないことがあったので勉強になりました。
この記事を読んで、この本から学ぶことが多そうな人は一度読んでみてもいいかもしれません。
おわり。