[パタヘネ:読書メモ]2章 命令:コンピュータの言葉

2.1 はじめに


コンピュータの言葉を、命令セットと呼ぶ(機械語/アセンブラの事)
アセンブラは、CPUが変わっても大きく違わない(方言レベル)。

命令セットの設計方針

コンパイラを実装しやすくする
性能の最大化
消費電力の最小化
シンプルである事



本書では、C言語と、アセンブラ命令の退避を行う
javaのようなOO言語の場合は、2.15節(CDROM)で別記されている


2.2 コンピュータ・ハードウエアの演算


まず、アセンブラ表記法の説明(これはMIPSのアセンブリ表記)

add a, b, c


は、Cでいうところの a = b + cと等価。


addのパラメータは必ず3つで、#以降の文字はコメント。
アセンブラでは、パラメータの事をオペランドと呼ぶ

add a, a, b   #この処理は a += b;と等価



addは2つの足し算しか出来ないので、a = b + c + d + eをする為には3命令必要

add a, b, c
add a, a, d
add a, a, e



オペランドを可変個にするとソフトウェアを書くのは楽だが、全ての命令でオペランドを固定(例だと3つ)にしてしまうと、ハードの設計が簡単になる。





p72:オペランド、アセンブリ言語の説明

オペランド

省略



レジスタは32個

$zero   常に0
$at     アセンブラに予約されている
$v0-$v1 式の評価と結果の保存用
$a0-$a3 引数(arg)
$t0-$t7 テンポラリ(呼び元によって保存される?)
$s0-$s7 テンポラリ(呼ばれた関数で保存される?)
$t8-$t9 テンポラリ(呼び元によって保存される?)
$gp
$sp     スタックポインタ
$fp     フレームポインタ
$ra     リターンアドレス



詳細は,mips_instructions.pdf


例題:f=(g+h)-(i+j)をアセンブリでどうあらわすか?
模範解答は以下の通り.

add $t0, g,   h
add $t1, i,   j
sub f,   $t0, $t1



疑問:でも、上記の場合は以下の答えもありな気がする。
こっちの方がtレジスタを使わないから良いと思うんだけど、どうなんだろう…

add f, g, h
sub f, f, i
sub f, f, j





2.3 コンピュータ・ハードウエアのオペランド


MIPSのレジスタ長は32bit
レジスタの数が少ない理由は2点

高速なストレージは高価
レジスタ数を増やすと機械語のビット数が増える(命令長が伸びる)



レジスタ番号は前述の$s0といった書き方ではなく$0~$31という数字だけの表記も理論上は可能だが、MIPSでは意味を示すアルファベット+連番の表記法になっている
以後、$s?は変数、$t?はワーク変数の意味で使う事にする。

なので、前節のアセンブラは厳密には以下が正しい。

add $t0, $s1, $s2
add $t1, $s3, $s4
sub $s0, $t0, $t1




沢山の変数や、構造体を管理したい場合はどうするか? このような場合は、メモリに情報を保存する。
メモリ->レジスタのコピーはlw(load word)命令,その逆はsw(store word)命令を使用する



例題1:
変数gに$s1, hに$s2をマッピングし, a[0]のアドレスが$s3に有るとき、以下の処理をアセンブラでどう表記されるか?

int a[100];
g = h + a[8];



回答

lw  $t0, 32($s3)   # wk0 = a[8] memo:配列1要素が4byteなので8*4=32を指定
add $s1, $s2, $t0  # g = h + wk0
int a[100];
g = h + a[8];



lw命令では、第二オペランドの括弧内にベースアドレスを表記する。
また、上記例のように各変数とレジスタ、配列とメモリアドレスの割付けはコンパイラの仕事。

メモリマッピングは、MIPSの場合はビッグエンディアン(big-endian)を採用している。




例題2:
以下のコードをアセンブルするとどうなるか?

int a[100];
a[12] = h + a[8];



回答

lw  $t0, 32($s3)   # wk0   =  a[8]
add $t0, $s2, $t0  # wk0   += h
sw  $t0, 48($s3)   # a[10] =  wk0



変数がレジスタ数より多くなる場合、一部のデータはメモリに退避させる必要がある。これをスピルアウト(spillout)と呼ぶ
メモリからディスクへのスワップアウトと(ストレージが変わっただけで)同じ意味合い。


定数の足し算はaddi(add immediate)命令を使用する
例えば a += 10は、下記のように表記できる

addi $s0, $s0, 10



4822284786
コンピュータの構成と設計(上)

関連記事

コメントを残す

メールアドレスが公開されることはありません。