パタヘネChapter3 part1

Chpter3--命令:マシンの言葉

3.1 はじめに p.96

コンピューターハードウェアに命令を伝えるには、コンピューターの言葉で話さなければならない。

  • コンピューター言語の言葉を命令(instruction)と呼び、
  • コンピューターの語彙を命令セット(instruction set)と呼ぶ。

すべてのコンピューターは同じ根本原理に基づくハードウェア技術を用いて造られている。と。
これが、コンピューターアーキテクチャーやコンパイラ開発を学ぶ理由の一つだなんて思ってます。

  • ハードウェアの設計に関する四つの基本原則
    1. 単純性は規則性につながる。
    2. 小さければ小さいほど高速になる。
    3. 優れた設計には適度な妥協が必要である。
    4. 一般的な場合を高速化せよ。

3.2 コンピューター・ハードウェアの演算 p.97

MIPSアセンブリ言語では、加算は下記のように示す。
add a, b, c
これはa = b + c;
を意味する。
ここで、加算に必要な要素a,b,cのことをオペランド(operand)という。
ハードウェアの単純性を保つという理念より、オペランド数は固定にした方が良い。
オペランドの数が可変なハードウェアは、オペランド数が固定のハードウェアよりも複雑になる。
そのため、先の基本原則の一つである

  • 単純性は規則性につながる

が導き出される。

例題

Cの二つの代入文のMIPSへのコンパイル

3オペランドで記述するだけ略
例題

Cの複雑な代入文のMIPSへのコンパイル

知っていれば簡単。同様に略

3.3 コンピューター・ハードウェアのオペランド p.99

算術命令のオペランドでは変数を指定することが出来ない
オペランドは特殊な記憶領域の中から選んで使用しなければならない。
その記憶領域のことをレジスタ(register)と呼ぶ。
MIPSアーキテクチャーにおいてレジスタ長は32ビットである。
32ビットを一まとめにしたものは頻繁に使用されるので、それを一つの単位として語(word)と呼んでいる。

レジスタの数は限られており、一般に現在のコンピューターに備えられているレジスタの数は32である。
レジスタ数に限りがある理由は、ハードウェア設計に関する四つの基本原則の一つである

  • 小さければ小さいほど高速になる

に由来する。

レジスタ数を増やすと、電気信号が送られる距離が増大し、クロックサイクル時間が増大するためである。
しかし、この指針は絶対的なものではない。
レジスタ数が31個の場合が32個の場合よりも速いとは限らない。しかし、この原則は観測に基づく真理である。
プログラマレジスタ数が多いことを望むが、コンピューターの設計者はクロックサイクルの速度を高速に保つこととのバランスを取らなければならない。

レジスタの番号を0から31の数値だけで書き表すことは可能であるが、
MIPSの表記法では、レジスタを表すのに$記号の後ろに2文字をつけた名前を使用する。
Cプログラム中の変数に対応するレジスタは$s0,$s1,...を使用し、
プログラムをMIPSの命令にコンパイルするために必要な一時レジスタには$t0,$t1,...を使用するとする。

例題

レジスタを使用したCの代入文のコンパイル

これも定義通りなので略

配列に含まれるデータ要素の数がレジスタの数を超える場合、メモリ中に保持することになる。

                   レジスタ         メモリ
記憶可能な量              僅か           膨大
データへのアクセス時間         一瞬          それなり
スループット              高い           低い

MIPSマシンにはメモリとレジスタの間でデータを転送する命令が備わっている。
そのような命令をデータ転送(data transfer)命令と呼ぶ。
メモリ内の語にアクセスするためには、命令中でメモリのアドレス(adress)を指定しなければならない。
メモリからレジスタへデータを転送するデータ転送命令を一般にロード(load)命令と呼ぶ。
ロード命令の記述形式は命令形式(operation)の名前、データをロードする先のレジスタ、メモリにアクセスするために使用する定数とレジスタの順。
MIPSではこの命令をlwと呼ぶ。(load word)
ロードと逆の命令をストア(store)と呼ぶ。
MIPDではこの命令をswと呼ぶ。(store word)

例題

オペランドがメモリ中にあるときの代入文のコンパイル

g = h + a[8];
lw $t0, 32($s3)
add $s1, $s2 $t0

配列の開始アドレスをベース・アドレス(base address)
データ転送命令中の定数をオフセット(offset)と呼び、アドレスを得るために加えるレジスタをベース・レジスタ(base register)と呼ぶ。
多くのプログラムにおいて8ビットのバイト(byte)が有用な役割を果たす。
MIPSでは、語アドレスは4の倍数でなければならない。この用件を整列化制約(alignment restriction)と呼ぶ。
バイト・アドレスを採用しているマシンには以下の二つのタイプがある。

  • 左端のバイト・アドレスを語のアドレスとして使用するビッグエンディアン方式(big-endian)
  • 右端のバイト・アドレスを語のアドレスとして使用するリトルエンディアン方式(little-endian)

0x0A0B0C0Dという値をメモリに格納する場合

となる。なお、これらの語はガリバー旅行記のエピソードに由来する。

例題

ロードとストアが使用されているコードのコンパイル

lw    $t0, 32($s3)
add $t0, $s2 $t0
sw  $t0 48($s3)
例題

配列インデックスに変数が使用されているコードのコンパイル

add $t0, $s4, $s4
add $t0, $t0, $t0
#これでiから4iをもとめた。
add $t0, $t0, $s3
#ベース・アドレスに4iを足す。
lw   $t1, 0($t0)
add $s1, $t1, $s2

使用頻度の低い変数、または後で必要となる変数をメモリ上に置くことをレジスタをスピルアウト(spilling)するという。