wiki:Ex01 MIPSアセンブリの基礎2015

Version 10 (modified by nakasato, 11 years ago) (diff)

--

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は常にゼロである。

複雑な式の評価

代入文の右辺が複雑な場合は式を変換して考えます。

A= B * C - 5

という演算をする場合、右辺は一時的な変数Tempを用いて、

Temp = B * C
A = Temp - 5

と変換できます。 より複雑な式も、このように一時的な変数を導入して分解して、右辺の演算が実装する命令で実行できるようにします。 if文の条件判定の式が複雑な場合も同様に分解します。

アセンブラプログラムでは、一時的な変数の役割はレジスタが行います。 しかし、すべての一時的なレジスタを使いきるような場合、一時変数を保持するのにメモリを利用する必要があります。 メモリを利用する場合、swおよびlw命令が必要となり、 実行命令数が増えるので、可能な限りレジスタを効率的に使用するようにします。

課題1

3つの変数と定数を含んだ式「S = (A + B - C) | 3」の計算を行うプログラムを作成し、SPIM上でシミュレーションを行ってください。 "|" はビットごとの論理和演算です。

各変数の初期値は以下のように設定してください。

アドレス データ(10進数)
A 19
B 75
C 10
S 結果の格納

例題2 レジスタによるメモリの参照

この例題ではメモリを間接的に参照するためにレジスタ相対アドレスを用いる方法を示します。 以下のような配列変数の和を計算することを考えます。

S=A[0]+A[1]+A[2]+A[3]

配列のように、連続するデータのアドレスが規則的に並んでいる場合、 レジスタを使ってアドレスを加減算しながらメモリにアクセスするとプログラムが簡単に記述できます。 たとえば次のようにデータが並んでいるとします。 

アドレス データ(10進数)
A 19
A+4 75
A+8 10
A+12 15 |
S 結果の格納

このような場合、最初のアドレスAがわかれば、次のアドレスはAに4を足すことによって求めることができます。 したがって、4つの要素の和を求める場合、次のようなプログラムを記述すればよいことになります。

        .data 
A:      .word 19 
        .word 75 
        .word 10 
        .word 15 
S:      .word 0
        .text 
main:   or   $8, $0, $0   # 和を 0 に初期化 
        la   $9, A        # Aのアドレスを $9 に入れる。実際は ori 命令に置き換わる。

        lw   $10, 0($9) 
        add  $8, $8, $10 

        lw   $10, 4($9) 
        add  $8, $8, $10

        lw   $10, 8($9) 
        add  $8, $8, $10

        lw   $10, 12($9) 
        add  $8, $8, $10

        sw   $8, S 
exit:   j exit

また、上のプログラムは下のように書き直すこともできます。 この形は各データに対する処理が全く同じ命令列になるため、 後で述べるループを用いて和を求める場合に適しています。

        .data 
A:      .word 19 
        .word 75 
        .word 10 
        .word 15 
S:      .word 0
        .text 
main:   or   $8, $0, $0   # 和を 0 に初期化 
        la   $9, A        # Aのアドレスを $9 に入れる。実際は ori 命令に置き換わる。

        lw   $10, 0($9) 
        add  $8, $8, $10  
        addi $9, $9, 4    # アドレスを次へすすめる

        lw   $10, 0($9) 
        add  $8, $8, $10 
        addi $9, $9, 4

        lw   $10, 0($9) 
        add  $8, $8, $10 
        addi $9, $9, 4

        lw   $10, 0($9) 
        add  $8, $8, $10

        sw   $8, S 
exit:   j exit

Attachments (1)

Download all attachments as: .zip