機械語に理解するために,以下の3つの抽象化についてだけ考えればよい.
1. メモリ
- コンピュータで,データや命令を保存するハードウェアデバイスを指す
- 各セルはワード,ロケーションとも呼ばれ,それぞれはユニークなアドレスを持つ
- Memory[address], RAM[address], M[address]と表現する
2. プロセッサ
3. レジスタ
- register, 登録所,仮置き場みたいな
個人的な例え
メモリ,プロセッサ,レジスタ,ストレージをビュッフェレストランで例える.
個人的な印象として,
- プロセッサ → ご飯を食べる人
- レジスタ → ご飯を食べる人のテーブルの上のお皿
- メモリ → フロアに置いてあるビュッフェ
- ストレージ → 厨房の冷蔵庫
って感じがする.
長期的に保存する食べ物は冷蔵庫に貯蓄し,その冷蔵庫の中にある食べ物は何らかの処理・加工を施してビュッフェとしてフロアに配置される. ご飯を食べる人はそのビュッフェから一時的に自分のお皿に盛り付け,その食べ物を処理する(食べていく).ご飯を食べる人からすると,ビュッフェは少し遠いもので,直接処理することは出来ない.一方で 机上の食事はすぐ手の届く位置にあり,処理しやすい.
機械語
バイナリコードは,人にとっては暗号めいているため,通常,バイナリコードとニーモニックの両方を用いて表される
ニーモニック
ADDとか,基本的に英語三文字の記号のこと.
- レジスタは基本的にR0, R1, R2 っていう表現をするよ
- 記号による抽象化によって,コードを読むだけじゃなくて,書くことも出来るようになるよ.
- 記号による表記をアセンブリ言語っていうよ.単にassemblyっていうこともあるよ
- アセンブリから機械語に変換するプログラムをassemblerっていうよ
ADD R0, R1, R2 // R0 = R1 + R2 AND R0, R1, R2 // R0 = R1 && R2
メモリアクセス
メモリアクセスを行うコマンドは2種類に分類される
- 算術演算,論理演算
- 読み込み・格納
1. 直接アドレシング (direct addressing)
アドレスを読み取って,メモリに格納されている情報を読み取る
LOAD R1, 67 // R1 = Memmory[67] LOAD R1, foo // R1 = Memmory[67] (変数を読み込ませる)
2. イミディエイトアドレッシング (immediate addressing)
定数を読み込む.
LOADI R1, 54 // R1 = 54
3. 間接アドレッシング (indirect addressing)
- ポインタを扱う際に用いるよ
- 高水準コード(C言語)における特定の配列を操作する際に用いるよ.
コンパイラの配列操作の仕組みをおさらい
- 高水準言語でfooという変数名で配列を宣言し,コンパイラに通す
- コンパイラは,その foo と名付けられた 配列データ のメモリ領域(セグメント)を割り振る
- セグメント*1のベースを参照する foo という記号を作る
つまり,
(高水準言語を書いた)人から見たfoo
は配列データを指すんだけど,
機械から見たfoo
は配列データの入口を示すアドレス値を指すんだね
// セグメントのベースアドレスを参照する例 // x = foo[j] もしくは,x = *(foo + j) の変換 ADD R1, foo, j // R1 = foo + j LOAD R2, R1 // R2 = Memory[R1] STR R2, x // x = R2
分岐命令
分岐命令の3つの手段
- 反復
- 条件分岐
- サブルーチン呼び出し
- 機械語は,プログラムの指定された位置へ戻る手段を持つ必要がある
- つまり,戻る指標が必要
Hack機械語の仕様
- Hackコンピュータ = ノイマン型のプラットフォーム
Hack メモリアドレス空間
- Hackは二つの異なるメモリ空間を持つ
- 命令メモリ (instruction memory) → 読み込み専用,ROM (read only memory)
- データメモリ (data memory)
- 両方とも16bit幅,サイズは32K
- CPUは,命令メモリだけ読み込める
Hack レジスタ
- DレジスタとAレジスタが存在する
- Dレジスタ
- データレジスタとしての役割,つまりデータを一時保存する場所.バッファーみたいなものかな
- コード書いてて思ったのは,Dは仮置き場って表現がしっくりくるかも
- Aレジスタ
このHackレジスタを図書館の司書さんで例えてみる.
A司書さんはよく働きます.きびきびと,アドレス(番地)を読み取って,その番地に対応する本棚から本を探して抜き取ります(参照).そして自分で本を持ちます. D司書さんはそんなにきびきび動きません.いちいち動いたり,高い棚にある本を少し背伸びして取るなんて面倒なので,基本的に本を持つことしかしません.Aレジスタさんから「これちょっと持ってて~」と言われて本を持つだけです.
Hack記法
レジスタと同様に2種類の命令から構成されるよ
A命令 (アドレス命令,address instruction)
@hoge
とかにあたる. 以下の3つの役割を持つ定数代入
- メモリ操作
- 移動命令
C命令 (計算命令,compute instruction)
bar;hoge
がこれにあたる- 111a cccc ccdd djjj というフォーマット
コードの最小単位は
@hoge M = 7
@hoge
などの@ + 文字列の場合,それはメモリのラベルを表す@7
などの@ + 数値の場合,Aに値そのものが入る- この2行でA司書さんは,番地を読み取って,その番地に対応する本棚から本を取り出して本を一時的に持ちます
その他やってて思ったこと
- @hoge などのラベルでも,機械側は結局 @16 とかに変換している
- 出力をきちんとRAM[2]に指定しないとアカン.テストで気づいた.
- CPU emulater にて Speed を Max に設定すると なんか楽しい(高速で行ったり来たりする)
*1:セグメント = 領域