Changes between Version 26 and Version 27 of Ex01 MIPSアセンブリの基礎2015
- Timestamp:
- Apr 14, 2015 9:44:35 AM (11 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Ex01 MIPSアセンブリの基礎2015
v26 v27 56 56 57 57 = 例題1:変数の代入 = 58 変数A, B, Cがある時に「C = A + B」を実現するプログラム を考える。59 60 変数A, B, Cは、メモリ上に以下のように配置されているとします。61 それぞれは32ビットワードの変数であり、 1変数につき4バイトのアドレス空間を占めます。58 変数A, B, Cがある時に「C = A + B」を実現するプログラムについて検討します。 59 60 変数A, B, Cは、メモリ上に以下のように配置されているとします。 61 それぞれは32ビットワードの変数であり、1変数につき4バイトのアドレス空間を占めます。 62 62 63 63 || 変数 || アドレス(16進数) || 初期値(10進数) || 結果(10進数) || … … 65 65 || B|| 0x4|| 75|| 75|| 66 66 || C|| 0x8|| 0|| 94|| 67 / 68 MIPSプロセッサでの演算は 、レジスタ間でのみ行うことができます。67 68 MIPSプロセッサでの演算はレジスタ間でのみ行うことができます。 69 69 したがって、メモリの中のデータを演算するためには一度レジスタの中にデータをロードし、 70 70 演算を行った後に演算結果をメモリにストアしなければなりません。 … … 86 86 このプログラムを「sum1.s」としてファイルに保存し、xspimでシミュレーションを行ってください。 87 87 88 アセンブリプログラムで 、「.data」から始まる部分をデータセグメントと呼びます。88 アセンブリプログラムで「.data」から始まる部分を、データセグメントと呼びます。 89 89 各行は「32ビット数値で内容は「19」の変数を定義しそのアドレスを「A」で参照できるようにする」という意味です。 90 90 … … 92 92 各命令の概要を以下のテーブルで説明します。 93 93 94 まず、このプログラムでは、レジスタ$8, $9, $10を利用していて、各行が実行される毎にその内容は変化する場合があります。 94 このプログラムでは、レジスタ$8, $9, $10を利用しています。 95 各行が実行される毎にその内容は変化する場合があります。 95 96 96 97 || 命令 || 動作 || $8の内容 || $9の内容 || $10の内容 || 97 || lw $8, A||アドレスAのデータをレジスタ$8にロード|| 19 || 不定 || 不定 ||98 || lw $9, B||アドレスBのデータをレジスタ$9にロード|| 19 || 75 || 不定 ||99 || add $10, $8, $9 ||レジスタ$8と$9を加算して、結果を$10に格納|| 19 || 75 || 94 ||100 ||sw $10, C ||レジスタ$10の内容をアドレスCにストア|| 19 || 75 || 94 ||101 ||j exit ||ラベルexitにジャンプ || 19 || 75 || 94 ||98 ||lw $8, A ||アドレスAのデータをレジスタ$8にロード|| 19 || 不定 || 不定 || 99 ||lw $9, B ||アドレスBのデータをレジスタ$9にロード|| 19 || 75 || 不定 || 100 ||add $10, $8, $9 ||レジスタ$8と$9を加算して、結果を$10に格納|| 19 || 75 || 94 || 101 ||sw $10, C ||レジスタ$10の内容をアドレスCにストア|| 19 || 75 || 94 || 102 ||j exit ||ラベルexitにジャンプ || 19 || 75 || 94 || 102 103 103 104 補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形であり、レジスタ$8には「A + $0」の値がロードされます。 104 105 105 x psimを実行すると以下のような画面となります。106 xspimを立ち上げると、以下のような画面となります。 106 107 107 108 [[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex01%E3%80%80MIPS%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%AA%E3%81%AE%E5%9F%BA%E7%A4%8E2015/xpsim.png)]] 108 109 109 110 110 画面の上段には各レジスタの内容が示されています。 111 111 112 中段には各ボタンがあり、ソースファイルの読み込みには "load" ボタン、プログラムの実行には "step" ボタンをクリックします。 113 114 下段にはテキストセグメント(Text Segments)と、データセグメント(Data Segments)が示され、一番下の部分には実行時のメッセージが表示されます。 112 中段には各ボタンがあり、ソースファイルの読み込みにはloadボタン、プログラムの実行にはstepボタンをクリックします。 113 114 下段にはテキストセグメント(Text Segments)と、データセグメント(Data Segments)が示され、 115 一番下の部分には実行時のメッセージが表示されます。 115 116 116 117 プログラムの実行には二つの方法があり、stepボタンによる実行では、テキストセグメントの命令が一命令ずつ実行されます。 117 一方 "run"ボタンを使うと、プログラムを一気に実行できます。118 119 このプログラムをstep実行し、一命令ずつレジスタやデータセグメントの値が変化するのを確かめること。118 一方runボタンを使うと、プログラムを一度に実行できます。 119 120 「sum1.s」をstep実行し、一命令ずつレジスタやデータセグメントの値が変化するのを確かめること。 120 121 121 122 = 複雑な式の評価 = … … 142 143 143 144 = 課題1 = 144 3つの変数と定数を含んだ式「S = (A + B - C) | 3」の計算を行うプログラムを作成し、 SPIM上でシミュレーションを行ってください。145 3つの変数と定数を含んだ式「S = (A + B - C) | 3」の計算を行うプログラムを作成し、xspimでシミュレーションを行ってください。 145 146 "|" はビットごとの論理和演算です。 146 147 … … 156 157 この例題ではメモリを間接的に参照するためにレジスタ相対アドレスを用いる方法を示します。 157 158 以下のような配列変数の和を計算することを考えます。 159 158 160 {{{ 159 161 S=A[0]+A[1]+A[2]+A[3] … … 202 204 203 205 また、上のプログラムは下のように書き直すこともできます。 204 この形は各データに対する処理が全く同じ命令列になるため、 205 後で述べるループを用いて和を求める場合に適しています。 206 この形は各データに対する処理が全く同じ命令列になるため、後で述べるループを用いて和を求める場合に適しています。 206 207 207 208 {{{ … … 213 214 S: .word 0 214 215 .text 215 main: or $8, $0, $0 # 和を 0 に初期化216 la $9, A # Aのアドレスを $9 に入れる。実際は ori 命令に置き換わる。216 main: or $8, $0, $0 217 la $9, A 217 218 218 219 lw $10, 0($9) … … 235 236 }}} 236 237 237 上の 2番目のアセンブリプログラムをエディタにコピー&ペーストして、SPIM上で動作を確認してください。238 上の2番目のプログラムをエディタにコピー&ペーストして、xspimで動作を確認してください。 238 239 レジスタをインクリメントしながらメモリにアクセスする方法を理解してください。 239 240 … … 243 244 244 245 {{{ 245 if( i == j) goto label 246 : 246 if(i == j) goto label 247 248 ... 249 247 250 label: 248 251 }}} … … 256 259 == 大小比較 == 257 260 大小比較をするには、set on less than命令、あるいはset less than imm命令と、beq命令を組み合わせて実現します。 261 258 262 === C言語 === 259 263 {{{ 260 if(a > b) {サブプログラム 1}else {サブプログラム2}264 if(a > b) {サブプログラム1}else {サブプログラム2} 261 265 }}} 262 266 … … 267 271 slt $8,$9,$8 268 272 beq $8,$0,label1 269 {サブプログラム1に対応するアセンブラプログラム} 273 274 サブプログラム1に対応するアセンブラプログラム 275 270 276 goto label2 271 277 label1: 272 {サブプログラム2に対応するアセンブラプログラム} 278 279 サブプログラム2に対応するアセンブラプログラム 280 273 281 label2: 274 282 }}} 275 283 276 「 <=」による条件分岐をどのように実現するか、また、「if (条件1 || 条件2)」や「if (条件1&& 条件2)」をどのように実現するかは各自検討してください。 284 「<=」による条件分岐をどのように実現するか、また、 285 「if (条件1 || 条件2)」や「if (条件1 && 条件2)」をどのように実現するかは各自検討してください。 277 286 278 287 == while文 == 279 288 === C言語 === 280 289 {{{ 281 while(条件){ サブプログラム }290 while(条件){ サブプログラム } 282 291 }}} 283 292 … … 287 296 $a ← if (条件) 1 else 0 288 297 beq $a,$0,label2 289 (サブプログラムに対応するアセンブラプログラム) 298 299 サブプログラムに対応するアセンブラプログラム 300 290 301 goto label1 291 302 }}} … … 307 318 308 319 と置き換えることができるので、while文のアセンブリプログラムを応用することで変換可能です。 320 309 321 このとき、iの値をレジスタに保持しておくと、iへのswやlw命令を省略でき、 310 322 高速化が行えますが、繰り返しの中で自由に使えるレジスタが減ってしまいます。 … … 314 326 = 例題3 ループによる演算 = 315 327 この例題では、1からnまでを単純に加算するプログラムを扱います。 328 316 329 == C言語 == 317 330 {{{ … … 342 355 ループ変数 i を$8、n の値が入っているレジスタを$9とすると、ループの部分は次のように書けます。 343 356 {{{ 344 or $8, $0, $0 # i = 0345 loop: beq $8, $9, loopend # i == n なら loopend へ飛ぶ346 addi $8, $8, 1# i++357 or $8, $0, $0 # i = 0 358 loop: beq $8, $9, loopend # i == n なら loopend へ飛ぶ 359 addi $8, $8, 1 # i++ 347 360 348 361 ・・・・ループの中身・・・・・ 349 362 350 j loop363 j loop 351 364 loopend: 352 365 }}} … … 376 389 プログラムの先頭部分(配列データ)には下のコードを使用してください。 377 390 {{{ 378 .data391 .data 379 392 N: .word 10 # The length of Array 380 393 A: .word 8 # A[0] = 8 381 .word 4 # A[1] = 4382 .word 7383 .word 12384 .word 13385 .word 19386 .word 23387 .word 43388 .word 56 # A[8] = 56389 .word 32 # A[9] = 32390 S: .word 0391 .text394 .word 4 # A[1] = 4 395 .word 7 396 .word 12 397 .word 13 398 .word 19 399 .word 23 400 .word 43 401 .word 56 # A[8] = 56 402 .word 32 # A[9] = 32 403 S: .word 0 404 .text 392 405 main: 393 406 }}} … … 397 410 プログラムの先頭部分には、下のコードを使用して下さい。 398 411 {{{ 399 .data412 .data 400 413 N: .word 10 # The length of Array 401 A: .word 8 # A[0] = 8402 .word 4 # A[1] = 4403 .word 7404 .word 12405 .word 13406 .word 19407 .word 23408 .word 43409 .word 56 # A[8] = 56410 .word 32 # A[9] = 32411 B: .space 40 # 配列B の格納先 大きさは40バイト412 .text414 A: .word 8 # A[0] = 8 415 .word 4 # A[1] = 4 416 .word 7 417 .word 12 418 .word 13 419 .word 19 420 .word 23 421 .word 43 422 .word 56 # A[8] = 56 423 .word 32 # A[9] = 32 424 B: .space 40 # 配列B の格納先 大きさは40バイト 425 .text 413 426 main: 414 427 }}}
