= SPIMの使用法および例題 = == 演習の目的 == * 命令レベルシミュレータに慣れること * MIPSのアセンブラ命令の使い方を理解すること * 今後の課題で使用するプログラムを作成すること 今回の演習ではMIPSプロセッサのアセンブラを用いて簡単なプログラミングを行います。 このプログラムを動作させるために、SPIMシミュレータを用いて、実際に正しく動作しているかどうかを確認します。 ここで作成したプログラムはあとで設計するMIPSプロセッサで実行させるテストプログラムになります。 == シミュレータのドキュメント == == 留意点 1 == 以下の表に示された以外の命令は使わないこと。 これ以外の命令を使うと、後半の演習で設計するMIPSプロセッサでは動作しません。ただし、他の命令に置き換えられる疑似命令は使用できます。 例えば la 命令は ori 命令に置き換えられるので使用できます。 レジスタの指定は、$0から$31でも、$zero,$v0,$v1,...でも構いません。 指定があるもの(スタックポインタ,リターンアドレスなど)は、指定通りに使ってください。 以下の課題において、一時的にレジスタを利用する場合は、$8から$15と$24, $25(これらは$t0 - $t9としてもアクセス可能)を使用します。 $1はアセンブラが使用するので、プログラムでは使用しないでください。 == 留意点 2 == シミュレーションはステップ実行で行うこと。方法については演習の時間に説明する。 == 留意点 3 == 後半の演習で設計するMIPSプロセッサでは、システムコールを実装しないので、exit システムコールは利用できません。 プログラムの最後で停止させたいときは、自分自身にジャンプさせ無限ループさせるようなコードを挿入します。 例: {{{ exit: j exit }}} == 留意点 4 == 後の演習や課題、レポートで利用するため、作成するプログラムは全て保存しておくこと。 = 単純な代入文 = 定数の代入文はor immediate命令とstore word命令の組み合わせで実現できます。 例えばC言語のコード {{{ A = 15; }}} は、擬似的なアセンブリプログラム {{{ $8 = 15; A = $8 }}} に置き換えることができます。 各行を実行可能な命令に置き換えると: {{{ ori $8, $0, 15 sw $8, A }}} というプログラムに置き換えることができます. == 考察事項 == * この2つのアセンブラ命令でA=15が正しく実現できているか考えなさい。 * なぜ$0が使われるのか? * この方法で扱える代入文の右辺の定数の範囲を考えなさい。 * 符号付き32bitの範囲の定数の代入文を実装する方法を考えなさい。 == メモリの初期化 == 代入文「A = 15;」は、Aへの代入としてプログラム開始から最初に実行され、一度しか実行されない場合 {{{ .data A: .word 15 }}} とすることで、アセンブリプログラムによるメモリ領域の初期化によっても実現できます。 しかし、この初期化を含んだプログラムをサブルーチンに用いる場合、一回目の実行でAの値が変更されてしまうと、 2回目以降の呼び出しにおいてAは15以外の値を持つ可能性があります。 この様な場合、上記のようにori命令とsw命令の組み合わせで代入文を実現します。 = 例題1:変数の代入 = 変数A, B, Cがある時に「C = A + B;」を実現するプログラムを考える。 変数A,B, Cは、メモリ上に以下のように配置されているとします。 それぞれは32ビットワードの変数であり、1変数につき4バイトのアドレス空間を占めます。 || 変数 || アドレス(16進数) || 初期値(10進数) || 結果(10進数) || || A || 0x0 || 19 || 19 || || B || 0x4 || 75 || 75 || || C || 0x8 || 0 || 94 || MIPSプロセッサでの演算はレジスタ間でのみ行うことができます。 したがって、メモリの中のデータを演算するためには一度レジスタの中にデータをロードし、 演算を行った後に演算結果をメモリにストアしなければなりません。 そのようなプログラムを下に示します。 {{{ .data A: .word 19 B: .word 75 C: .word 0 .text main: lw $8, A lw $9, B add $10, $8, $9 sw $10, C exit: j exit }}} このプログラムを「sum1.s」としてファイルに保存し、xspimでシミュレーションを行ってください。 ソースファイルの読み込みには "load" ボタン、プログラムの実行には "step" ボタンをクリックする。 「.data」で定義される部分をデータセグメントと呼ぶ。。各行は「32ビット数値で内容は「19」の変数を定義しそのアドレスを「A」で参照できるようにする」のような意味を持つ。 「.text」で定義される部分をコードセグメントと呼び、これがプログラムの本体になる。各命令の概要を以下に説明する。 まず、このプログラムでは、レジスタ$8, $9, $10を利用している。各行が実行される毎に、その内容は変化する場合がある。 || 命令 || 動作 || $8の内容 || $9の内容 || $10の内容 || || lw $8, A ||アドレスAのデータをレジスタ$8にロード|| 19 || 不定 || 不定 || || lw $9, B ||アドレスBのデータをレジスタ$9にロード|| 19 || 75 || 不定 || || add $10, $8, $9 ||レジスタ$8と$9を加算して、結果を$10に格納|| 19 || 75 || 94 || ||sw $10, C ||レジスタ$10の内容をアドレスCにストア|| 19 || 75 || 94 || ||j exit ||ラベルexitにジャンプ || 19 || 75 || 94 || 補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形である。レジスタ$0は常にゼロである。