Changes between Version 21 and Version 22 of Ex01 MIPSアセンブリの基礎2015
- Timestamp:
- Apr 12, 2015 8:48:13 PM (11 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Ex01 MIPSアセンブリの基礎2015
v21 v22 6 6 * 今後の課題で使用するプログラムを作成すること 7 7 8 今回の演習ではMIPSプロセッサのアセンブラを用いて簡単なプログラミングを行います。 9 このプログラムを動作させるために、SPIMシミュレータを用いて、実際に正しく動作しているかどうかを確認します。 8 今回の演習ではMIPSプロセッサのシミュレータをを用いてプログラミングを行います。 10 9 ここで作成したプログラムはあとで設計するMIPSプロセッサで実行させるテストプログラムになります。 11 10 … … 16 15 以下のページの留意点をよく読んでから演習を始めてください:[wiki:"Ex01 演習の留意点2015"] 17 16 18 19 17 = 単純な代入文 = 20 18 定数の代入文はor immediate命令とstore word命令の組み合わせで実現できます。 … … 40 38 41 39 == 考察事項 == 42 * この2つのアセンブ ラ命令でA=15が正しく実現できているか考えなさい。40 * この2つのアセンブリ命令でA=15が正しく実現できているか考えなさい。 43 41 * なぜ$0が使われるのか? 44 42 * この方法で扱える代入文の右辺の定数の範囲を考えなさい。 … … 46 44 47 45 = メモリの初期化 = 48 代入文「A = 15 ;」は、Aへの代入としてプログラム開始から最初に実行され、一度しか実行されない場合46 代入文「A = 15」は、Aへの代入としてプログラム開始から最初に実行され、一度しか実行されない場合 49 47 {{{ 50 48 .data … … 52 50 }}} 53 51 とすることで、アセンブリプログラムによるメモリ領域の初期化によっても実現できます。 54 しかし、この初期化を含んだプログラムをサブルーチンに用いる場合、 一回目の実行でAの値が変更されてしまうと、55 2回目以降の呼び出しにおいてAは15以外の値を持つ可能性があります。52 しかし、この初期化を含んだプログラムをサブルーチンに用いる場合、 53 1回目の実行でAの値が変更されてしまうと、2回目以降の呼び出しにおいてAは15以外の値を持つ可能性があります。 56 54 この様な場合、上記のようにori命令とsw命令の組み合わせで代入文を実現します。 57 55 58 56 = 例題1:変数の代入 = 59 変数A, B, Cがある時に「C = A + B ;」を実現するプログラムを考える。57 変数A, B, Cがある時に「C = A + B」を実現するプログラムを考える。 60 58 61 59 変数A,B, Cは、メモリ上に以下のように配置されているとします。 … … 67 65 || C|| 0x8|| 0|| 94|| 68 66 69 MIPSプロセッサでの演算は レジスタ間でのみ行うことができます。67 MIPSプロセッサでの演算は、レジスタ間でのみ行うことができます。 70 68 したがって、メモリの中のデータを演算するためには一度レジスタの中にデータをロードし、 71 69 演算を行った後に演算結果をメモリにストアしなければなりません。 … … 88 86 ソースファイルの読み込みには "load" ボタン、プログラムの実行には "step" ボタンをクリックする。 89 87 90 「.data」で定義される部分をデータセグメントと呼ぶ。各行は「32ビット数値で内容は「19」の変数を定義しそのアドレスを「A」で参照できるようにする」のような意味を持つ。 91 92 「.text」で定義される部分をコードセグメントと呼び、これがプログラムの本体になる。各命令の概要を以下に説明する。 93 まず、このプログラムでは、レジスタ$8, $9, $10を利用している。各行が実行される毎に、その内容は変化する場合がある。 88 「.data」で定義される部分をデータセグメントと呼びます。 89 各行は「32ビット数値で内容は「19」の変数を定義しそのアドレスを「A」で参照できるようにする」のような意味を持ちます。 90 91 「.text」で定義される部分をコードセグメントと呼び、これがプログラムの本体になります。 92 各命令の概要を以下のテーブルで説明します。 93 94 まず、このプログラムでは、レジスタ$8, $9, $10を利用していて、各行が実行される毎にその内容は変化する場合があります。 94 95 95 96 || 命令 || 動作 || $8の内容 || $9の内容 || $10の内容 || … … 100 101 ||j exit ||ラベルexitにジャンプ || 19 || 75 || 94 || 101 102 102 補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形であ る。レジスタ$0は常にゼロである。103 補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形であり、レジスタ$8には「A + $0」の値がロードされます。 103 104 104 105 = 複雑な式の評価 = … … 107 108 A= B * C - 5 108 109 }}} 110 109 111 という演算をする場合、右辺は一時的な変数Tempを用いて、 112 110 113 {{{ 111 114 Temp = B * C … … 113 116 }}} 114 117 と変換できます。 118 115 119 より複雑な式も、このように一時的な変数を導入して分解して、右辺の演算が実装する命令で実行できるようにします。 116 120 if文の条件判定の式が複雑な場合も同様に分解します。 117 121 118 アセンブ ラプログラムでは、一時的な変数の役割はレジスタが行います。122 アセンブリプログラムでは、一時的な変数の役割はレジスタが行います。 119 123 しかし、すべての一時的なレジスタを使いきるような場合、一時変数を保持するのにメモリを利用する必要があります。 120 124 メモリを利用する場合、swおよびlw命令が必要となり、 … … 133 137 ||S || 結果の格納 || 134 138 135 136 139 = 例題2 レジスタによるメモリの参照 = 137 140 この例題ではメモリを間接的に参照するためにレジスタ相対アドレスを用いる方法を示します。 … … 141 144 }}} 142 145 143 配列のように 、連続するデータのアドレスが規則的に並んでいる場合、146 配列のように連続するデータのアドレスが規則的に並んでいる場合、 144 147 レジスタを使ってアドレスを加減算しながらメモリにアクセスするとプログラムが簡単に記述できます。 145 148 たとえば次のようにデータが並んでいるとします。 … … 216 219 }}} 217 220 218 上の2番目のアセンブ ラソースファイルをエディタにカット&ペーストして、SPIM上で動作を確認してみてください。221 上の2番目のアセンブリプログラムをエディタにコピー&ペーストして、SPIM上で動作を確認してください。 219 222 レジスタをインクリメントしながらメモリにアクセスする方法を理解してください。 220 223 … … 244 247 === MIPSアセンブリ === 245 248 {{{ 246 lw $8, a // $8 = a247 lw $9, b // $9 = b248 slt $8,$9,$8 // $8 = if ($9<$8) $8=1;else $8=0249 beq $8,$0,label1 // if $8=0 then goto label1249 lw $8, a 250 lw $9, b 251 slt $8,$9,$8 252 beq $8,$0,label1 250 253 {サブプログラム1に対応するアセンブラプログラム} 251 254 goto label2 … … 277 280 for( i = init_value; i < terminate_value ;更新式){サブプログラム} 278 281 }}} 282 279 283 のようなfor文は、while文を使って 284 280 285 {{{ 281 286 i = init_value; … … 284 289 更新式} 285 290 }}} 291 286 292 と置き換えることができるので、while文のアセンブリプログラムを応用することで変換可能です。 287 293 このとき、iの値をレジスタに保持しておくと、iへのswやlw命令を省略でき、 … … 290 296 この場合繰り返しの最後に、レジスタの値をメモリに書き戻さないと、正しい最適化とはなりません. 291 297 292 = 例題3 アセンブラでのループ S=Σi=1..ni=293 この例題では、 1からnまでを単純に加算するプログラムを扱います。298 = 例題3 ループによる演算 = 299 この例題では、1からnまでを単純に加算するプログラムを扱います。 294 300 == C言語 == 295 301 {{{ … … 305 311 } 306 312 }}} 313 307 314 総和演算のような処理は処理はwhile文を用いることによって記述できます。 308 315 309 316 === MIPSアセンブリ === 310 アセンブラでは、分岐命令と比較命令を用いてループを実現します。メモリの初期状態を以下のように仮定しましょう。 317 アセンブリプログラムでは、分岐命令と比較命令を用いてループを実現します。 318 メモリの初期状態を以下のように仮定します。 311 319 312 320 || アドレス || データ || … … 314 322 || s || 結果の格納 || 315 323 316 このコードをアセンブラに変換します。 324 このコードをアセンブリプログラムに変換します。 325 317 326 ループ変数 i を$8、n の値が入っているレジスタを$9とすると、ループの部分は次のように書けます。 318 {{{327 {{{ 319 328 or $8, $0, $0 # i = 0 320 329 loop: beq $8, $9, loopend # i == n なら loopend へ飛ぶ … … 388 397 main: 389 398 }}} 390 391 392 393 394
