アセンブリ言語の演習にはMIPSのシミュレータであるSPIMを使用します。通常アセンブリ言語で書いたコードの実行にはアセンブラによる機械語への変換が必要ですが、SPIMは対話的な環境ですので、アセンブラは用いません。
SPIMを使用するには、ターミナル上で spim コマンドを実行します。下記の例ではspimを起動し、アセンブリコードtotal-10.sを読み込んで(load)、実行(run)しています。「(spim) 」はspimのプロンプトです。runの直後の55はプログラムが出力した結果で、改行されずに次のプロンプトが続いています。
コマンド | 機能 |
---|---|
load "ファイル名" | プログラムの読み込み |
run | プログラムの実行 |
exit, quit | spimの終了 |
改行 | 直前のコマンドの繰り返し |
reinitialize | メモリーとレジスターの初期化(プログラムを再読み込みする際に必要) |
? | コマンド一覧の表示 |
システムコールとはOSが提供する機能を呼び出すメカニズムで、用意されるシステムコールは OS 毎に異なります。
SPIMは汎用的なシミュレータで、特定のOSを想定しているわけではないため、SPIM独自のシステムコールが用意されています。以下にSPIMが提供しているシステムコールの内、代表的なものを載せます。
システムコールを利用する時は、$v0に利用したいシステムコールコードをセットし、必要であれば$a0などの引数も設定してsyscallを実行します。
SPIMではシステムコールを利用しても レジスタの値が破壊されないため、$s0~$s7以外のレジスタの値がシステムコール呼び出し後も継続して利用できてしまいます。また、SPIM起動直後はレジスタやメモリーの内容も全てゼロになっているため、初期化しなくても計算に利用できてしまいます。しかし、これは一般的なアセンブリ言語によるプログラムの振る舞いではないことに注意して下さい。
サービス | システムコール コード ($v0 で指定する) |
引数 | 結果 |
---|---|---|---|
print_int | 1 | $a0 = integer | |
print_float | 2 | $f12 = float | |
print_double | 3 | $f12 = double | |
print_string | 4 | $a0 = string | |
read_int | 5 | $v0 ← integer | |
read_float | 6 | $f0 ← float | |
read_double | 7 | $f0 ← double | |
read_string | 8 | $a0 = buffer $a1 = length |
引数 $a0 で指定したアドレスに格納される |
シミューレータSPIMは多くの疑似命令を用意しており、MIPSの命令にはない記述をかなり自由に書けてしまいます。たとえば分岐命令には即値との比較はありませんが、下記のような記述が許されています。
これは実際には以下のように展開されます。
これは10回の繰り返しを実現したプログラムの例ですが、この例では繰り返し内で毎回定数10をレジスタ$atに格納することになり、 これと同様の処理を繰り返しの外に出せば無駄を省けることが分かります。さらに繰り返しの制御を0から始めて上限値の10で停める場合はレジスタをこのために1つ使用するため、10 から0へと変化させる場合よりも余分にレジスタを使うことが分かります。
CPUの振舞いを正しく理解するためにも、むやみにSPIMの疑似命令を使用せず、この教材に載せた命令(推薦図書「コンピュータの仕組み」と同等)の範疇でプログラムを書くようにしましょう。