この記事は昔書いたレポートを一部改稿したものである。
せっかく書いたので公開したかったのだが、レポートの著作権が懸念事項となっていたため公開していなかった。
しかし京都芸術大学もOKと言っていることだし公開することにした。
ただ、先のリンクでは「1回公開すると、自分で書いた文章であっても引用時に出典の明記が必要となる」とも書かれているため、そのあたりは注意が必要である。
そのため、いつもの記事に比べ表現が硬すぎる気もするが気にしないでほしい。
なお、内容についてはほとんど覚えていないので、誤った点もあると思うがご容赦願いたい。
SPIMシミュレータを用いた加算プログラムの実行について、シミュレータのインストールを含めた実施内容と、理解したことを以下にまとめる。
1. SPIMシミュレータのインストール
今回はQtSpimと呼ばれるSPIMシミュレータを使用する。
QtSpimはhttps://sourceforge.net/projects/spimsimulator/files/
からダウンロードできる。
図1にQtSpimのダウンロードページを示す。
今回はwindows用の最新バージョンである”QtSpim_9.1.21_Windows.msi”を選択してダウンロードした。図1内の”Download Latest Version”と書かれた緑色のボタンを押すことでダウンロードできる。
保存したファイルを開くとインストーラが起動する。ライセンスに同意し、インストール先を決めてから、Installを押すとインストールが始まる。完了したらFinishを押してインストーラを閉じる。
図2にQtSpim起動時の状態を示す(詳しくないので一応レジスタ情報が書かれた部分についてはモザイク処理した)。QtSpimを起動すると2つのウィンドウが立ち上がるが、
- 図2の左側のメインウィンドウを使用してプログラムを実行し、
- 出力値があれば右側のコンソールに表示される
形となる。
図3にメインウィンドウを示す。
- 図左側には各レジスタに格納された値が
- 右側には様々なデータが
表示されている。
プログラムの実行などには上部のツールバーを使用する。
2. プログラムの実行方法と記述方式
プログラムの基本的な実行手順は次の通りである。
図3上部のツールバーから”File”→”Load File”を選択してプログラムファイルをロードし、”Simulator”→”Run”で実行する。
再実行する際は”Simulator”→”Clear Registers”でレジスタの内容を消去してから、先ほどと同様に”Run”で実行すればよい。
実行するプログラムは拡張子が.asmのファイルであり、これは別のエディタを用いて作成することになる。
プログラムの記述方式については、マニュアルに含まれている”Assemblers, Linkers, and the SPIM Simulator”という文書[1]のFigure1.4に例が掲載されている。マニュアルはツールバーから”Help”→”View Help”を選択すると参照できる。
図4にプログラムの記述例(Figure1.4)[1]を示す。C言語と同様に、main
内がメインルーチンを表している。今回作成するのは加算プログラムなので、図4の一部の記法だけ参考にすればよい。
以下、参考にした記法について、文書内の記述をもとに軽く解説する。
1行目の.text
は、この行の下に命令が記述されていることを表す。
2行目の.align 2
はデータを2バイト区切りで扱うことを示す。
3行目の.globl main
はmainラベルのスコープをグローバルに設定する。
4行目のmain:
はラベルであり、次のラベルまでの命令がmain
内にあることを示す。C言語で言うint main(void) {}
のような物をイメージしてもらえばよい。
最後から5行目のjr $ra
で呼び出し元のアドレスに戻る。C言語のreturn
のような物である。
図5に用意されているレジスタの詳細を示す。これは上記の文書[1]内のFigure6.1に記述されたものである。
この図から分かるように、$zero
がゼロレジスタ、$a0
~$a3
が引数を表している。図4の例にあった$ra
が戻り番地を示していることも読み取れる。
3. 加算プログラムの作成と実行
以上の情報を参考にして加算プログラムを作っていく。ここでは「レジスタ0に1を、レジスタ1に2を代入して、その和をレジスタ2に代入する」というプログラムを作成することにする。
作成した加算プログラムを図6に示す。
1行目から3行目は前述した設定のための記述であり、実際の計算は5~9行目のmain
ラベル内で行われている。以下、そのプログラム内容を説明する。
6行目でゼロレジスタの値と即値を足してレジスタ0に代入し、7行目も同様にしてレジスタ1に即値を代入する。
8行目でレジスタ0とレジスタ1の値を足し合わせ、結果をレジスタ2に代入する。
最後に9行目の命令で戻り番地にジャンプする。
加算プログラムの実行結果を図7に示す。左側に表示されたレジスタの値を見ると、レジスタ0 (a0) に1、レジスタ1 (a1) に2、レジスタ2 (a2) に3が格納されていることがわかるから、設計通りに加算プログラムが動作したと言える。
4. 感想
実際にアセンブリ言語を扱う際には、使うレジスタの種類をよく考える必要があると思った。
例えば図5に示した通り、引数はa0~a3に、一時データはs0~s7に保存するといった制限が明確に定義されているため、どの値をどのレジスタに格納するかよく考えずにプログラムを設計すると、使えるレジスタがなくなってしまう危険性があるからだ。
今回作成したプログラムではその心配がないためa0~a2レジスタのみを用いたが、例えばa0,a1レジスタをs0,s1レジスタで代用するなどすれば、プログラムの拡張がしやすくなるように感じた。
5. 参考文献
マニュアルに含まれてはいるが、ちゃんと元の文書のリンクを明記しておくべきだと思ったため書いておく。
[1] 「Assemblers, Linkers, and the SPIM Simulator」、James R. Larus、http://pages.cs.wisc.edu/~larus/HP_AppA.pdf (2021年10月10日閲覧)