Changes between Version 21 and Version 22 of Ex01 MIPSアセンブリの基礎2015


Ignore:
Timestamp:
Apr 12, 2015 8:48:13 PM (11 years ago)
Author:
nakasato
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Ex01 MIPSアセンブリの基礎2015

    v21 v22  
    66 * 今後の課題で使用するプログラムを作成すること 
    77  
    8 今回の演習ではMIPSプロセッサのアセンブラを用いて簡単なプログラミングを行います。 
    9 このプログラムを動作させるために、SPIMシミュレータを用いて、実際に正しく動作しているかどうかを確認します。 
     8今回の演習ではMIPSプロセッサのシミュレータをを用いてプログラミングを行います。 
    109ここで作成したプログラムはあとで設計するMIPSプロセッサで実行させるテストプログラムになります。 
    1110 
     
    1615以下のページの留意点をよく読んでから演習を始めてください:[wiki:"Ex01 演習の留意点2015"] 
    1716 
    18  
    1917= 単純な代入文 =  
    2018定数の代入文はor immediate命令とstore word命令の組み合わせで実現できます。 
     
    4038 
    4139== 考察事項 ==  
    42  * この2つのアセンブ命令でA=15が正しく実現できているか考えなさい。 
     40 * この2つのアセンブ命令でA=15が正しく実現できているか考えなさい。 
    4341 * なぜ$0が使われるのか? 
    4442 * この方法で扱える代入文の右辺の定数の範囲を考えなさい。 
     
    4644 
    4745= メモリの初期化 = 
    48 代入文「A = 15;」は、Aへの代入としてプログラム開始から最初に実行され、一度しか実行されない場合 
     46代入文「A = 15」は、Aへの代入としてプログラム開始から最初に実行され、一度しか実行されない場合 
    4947{{{ 
    5048    .data 
     
    5250}}} 
    5351とすることで、アセンブリプログラムによるメモリ領域の初期化によっても実現できます。 
    54 しかし、この初期化を含んだプログラムをサブルーチンに用いる場合、一回目の実行でAの値が変更されてしまうと、 
    55 2回目以降の呼び出しにおいてAは15以外の値を持つ可能性があります。 
     52しかし、この初期化を含んだプログラムをサブルーチンに用いる場合、 
     531回目の実行でAの値が変更されてしまうと、2回目以降の呼び出しにおいてAは15以外の値を持つ可能性があります。 
    5654この様な場合、上記のようにori命令とsw命令の組み合わせで代入文を実現します。 
    5755 
    5856= 例題1:変数の代入 =  
    59 変数A, B, Cがある時に「C = A + B;」を実現するプログラムを考える。 
     57変数A, B, Cがある時に「C = A + B」を実現するプログラムを考える。 
    6058 
    6159変数A,B, Cは、メモリ上に以下のように配置されているとします。 
     
    6765||     C|| 0x8||  0|| 94|| 
    6866 
    69 MIPSプロセッサでの演算はレジスタ間でのみ行うことができます。 
     67MIPSプロセッサでの演算はレジスタ間でのみ行うことができます。 
    7068したがって、メモリの中のデータを演算するためには一度レジスタの中にデータをロードし、 
    7169演算を行った後に演算結果をメモリにストアしなければなりません。 
     
    8886ソースファイルの読み込みには "load" ボタン、プログラムの実行には "step" ボタンをクリックする。 
    8987 
    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を利用していて、各行が実行される毎にその内容は変化する場合があります。 
    9495 
    9596|| 命令         || 動作 || $8の内容 || $9の内容 || $10の内容 || 
     
    100101||j  exit  ||ラベルexitにジャンプ || 19 || 75 || 94 || 
    101102  
    102 補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形である。レジスタ$0は常にゼロである 
     103補足:「lw $8, A」 は 「lw $8, A($0)」 の省略形であり、レジスタ$8には「A + $0」の値がロードされます 
    103104 
    104105= 複雑な式の評価 = 
     
    107108A= B * C - 5 
    108109}}} 
     110 
    109111という演算をする場合、右辺は一時的な変数Tempを用いて、 
     112 
    110113{{{ 
    111114Temp = B * C 
     
    113116}}} 
    114117と変換できます。 
     118 
    115119より複雑な式も、このように一時的な変数を導入して分解して、右辺の演算が実装する命令で実行できるようにします。 
    116120if文の条件判定の式が複雑な場合も同様に分解します。 
    117121 
    118 アセンブプログラムでは、一時的な変数の役割はレジスタが行います。 
     122アセンブプログラムでは、一時的な変数の役割はレジスタが行います。 
    119123しかし、すべての一時的なレジスタを使いきるような場合、一時変数を保持するのにメモリを利用する必要があります。 
    120124メモリを利用する場合、swおよびlw命令が必要となり、 
     
    133137||S ||  結果の格納 || 
    134138 
    135   
    136139= 例題2 レジスタによるメモリの参照 = 
    137140この例題ではメモリを間接的に参照するためにレジスタ相対アドレスを用いる方法を示します。 
     
    141144}}} 
    142145 
    143 配列のように連続するデータのアドレスが規則的に並んでいる場合、 
     146配列のように連続するデータのアドレスが規則的に並んでいる場合、 
    144147レジスタを使ってアドレスを加減算しながらメモリにアクセスするとプログラムが簡単に記述できます。 
    145148たとえば次のようにデータが並んでいるとします。   
     
    216219}}}  
    217220 
    218 上の2番目のアセンブラソースファイルをエディタにカット&ペーストして、SPIM上で動作を確認してみてください。 
     221上の2番目のアセンブリプログラムをエディタにコピー&ペーストして、SPIM上で動作を確認してください。 
    219222レジスタをインクリメントしながらメモリにアクセスする方法を理解してください。  
    220223 
     
    244247=== MIPSアセンブリ === 
    245248{{{ 
    246 lw $8, a // $8 = a 
    247 lw $9, b // $9 = b 
    248 slt $8,$9,$8 // $8 = if ($9<$8) $8=1;else $8=0 
    249 beq $8,$0,label1 // if $8=0 then goto label1 
     249lw $8, a 
     250lw $9, b 
     251slt $8,$9,$8 
     252beq $8,$0,label1 
    250253{サブプログラム1に対応するアセンブラプログラム} 
    251254goto label2 
     
    277280for( i = init_value; i < terminate_value ;更新式){サブプログラム} 
    278281}}} 
     282 
    279283のようなfor文は、while文を使って 
     284 
    280285{{{ 
    281286i = init_value; 
     
    284289更新式} 
    285290}}} 
     291 
    286292と置き換えることができるので、while文のアセンブリプログラムを応用することで変換可能です。 
    287293このとき、iの値をレジスタに保持しておくと、iへのswやlw命令を省略でき、 
     
    290296この場合繰り返しの最後に、レジスタの値をメモリに書き戻さないと、正しい最適化とはなりません. 
    291297 
    292 = 例題3 アセンブラでのループ S=Σi=1..ni = 
    293 この例題では、1からnまでを単純に加算するプログラムを扱います。 
     298= 例題3 ループによる演算 = 
     299この例題では、1からnまでを単純に加算するプログラムを扱います。 
    294300== C言語 == 
    295301{{{ 
     
    305311} 
    306312}}} 
     313 
    307314総和演算のような処理は処理はwhile文を用いることによって記述できます。 
    308315 
    309316=== MIPSアセンブリ === 
    310 アセンブラでは、分岐命令と比較命令を用いてループを実現します。メモリの初期状態を以下のように仮定しましょう。  
     317アセンブリプログラムでは、分岐命令と比較命令を用いてループを実現します。 
     318メモリの初期状態を以下のように仮定します。  
    311319  
    312320|| アドレス || データ || 
     
    314322|| s ||         結果の格納 || 
    315323 
    316 このコードをアセンブラに変換します。 
     324このコードをアセンブリプログラムに変換します。 
     325 
    317326ループ変数 i を$8、n の値が入っているレジスタを$9とすると、ループの部分は次のように書けます。  
    318  {{{ 
     327{{{ 
    319328         or  $8, $0, $0           # i = 0  
    320329loop: beq  $8, $9, loopend  # i == n なら loopend へ飛ぶ  
     
    388397main:  
    389398}}} 
    390  
    391  
    392  
    393  
    394