以下の課題問題を解き、レポートとして提出せよ。
動作を確認するためにトレース実行中に表示すべきデバイス名を考えて、
そのデバイスの値の変化を調べ、各プログラムがどのように動作しているかを
説明せよ。
(シミュレータへの入力内容と実行結果も示すこと)
※ 課題1.の例題番号は ((学籍番号の下2桁 + 4) mod 7) + 1 とする。
例えば、t102995の場合は、((95 + 4) mod 7) + 1 == 2 なので、例4.2の
マイクロプログラムを実行する。
課題1と同様に、
動作を確認するためにトレース実行中に表示すべきデバイス名を考えて、
そのデバイスの値の変化を調べ、各プログラムがどのように動作しているかを
説明せよ。
(シミュレータへの入力内容と実行結果も示すこと)
※ 課題2.の例題番号は ((学籍番号の下2桁 + 4) mod 3) + 2 とする。
例えば、t102995の場合は、((95 + 4) mod 3) + 2 == 2 なので、例5.2の
機械語プログラムを実行する。
一方、課題1(マイクロプログラム)では、 プログラムが使用するデバイスのいくつかについて値を初期設定する必要があるが、 これはプログラムによって異なる。 プログラムの動作を理解した上でどのデバイスにどういう値を設定するべきかを 考えること。
2012/4/25追記
命令レジスタIRの値の求め方は以下の通り。
例えば、値を2にする場合、2進表現は 10
Raは上から5番目と6番目のビットに対応するので、
その部分にRbの 2進表現の値を埋め込む。
同様にして、
Rbは上から7番目と8番目のビットに対応するので、
その部分にRbの 2進表現を埋め込む。
RaとRb以外の値は何でもよい。
例えば、Raを 11に、Rbを 01にする場合、
16ビットの2進表現 XXXX1101XXXXXXXXを得る。
※Xの部分は0と1のどちらでもよい。
例えば、0101110110101011を16進表現にする場合、
4桁ずつ区切った 0101 1101 1010 1011をそれぞれ
16進表現に変えて、5DABを得る。
0000 => 0 0001 => 1 0020 => 2 0011 => 3
0100 => 4 0101 => 5 0110 => 6 0111 => 7
1000 => 8 1001 => 9 1010 => A 1011 => B
1100 => C 1101 => D 1110 => E 1111 => F
※ベクトルの各要素を正の値、負の値、0にするなど入力データをいろいろ
変えて動作確認を行うこと。
※片方の値が0の場合や負の値を与えた場合の動作についても確認すること。ユークリッドの互除法 1. MをNで除算した結果の余りを Rとする 2. R≠0 ならば 3aへ。R=0 ならば 3bへ。 3a. M := N、 N := Rとして 1へ。 3b. Nの値が最大公約数となる。
※nの値が0の場合や、極端に大きい値の場合の動作についても確認すること。fib(1) = 1; fib(2) = 1; fib(n) = fib(n-1) + fib(n-2);
4の倍数は閏年 ただし、100の倍数は平年とし、400の倍数は閏年とする 例:西暦1900年は平年、2000年は閏年、2001年は平年、2012年は閏年、2100年は平年、2400年は閏年
2 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 (配列A) 2 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 (配列B) ↓ 一致する場合は主記憶上に判定結果として FFFFを格納する。
※最低でも長さ10以上の配列データを使って動作確認をした実行結果を示すこと。2 7 1 8 2 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 (配列A) 2 7 1 8 9 8 1 8 2 8 4 5 9 0 4 5 2 3 5 3 (配列B) ↓ 一致しない場合はデータが異なる位置を主記憶上に格納する。 先頭からのオフセット値(先頭を0とする)を格納すること。(この例の場合は0004)
また、スタックのサイズは有限であるため、深いレベルでサブルーチン呼び出しを
行ったり、連続してpush命令を使って大量のデータをスタック上に保存したり
しないように注意すること。
2012/4/27追記
例えば、
以下の命令コードを実行すると、レジスタ2に値 30 (16進表記で 1E)が格納される。
また、以下の命令コードを実行すると、
レジスタ1に商、レジスタ0に余りが格納される。
被除数が16ビット以内に収まる値の場合は、除算命令を実行する前に
上位16ビット(この場合はレジスタ0)に0をセットするのを忘れないこと。
第2オペランドにおいて、カッコを付けないときは定数、カッコを付けると
レジスタの指定になる。
命令レジスタの ND部は 8ビットの長さしかないので、指定可能な値は0〜255となる。
これより大きい値を指定してもアセンブラはエラーにしないが、
実際の機械命令コードは下位8ビットの値だけが使われるので注意する。
例えば、以下のような命令コードでもエラーにはならないが、
実際の値は下位8ビットの値なので、予想外の動作になる。
レジスタ1(上位16ビット)には0が格納されることに注意する。
LC 1,10 ←レジスタ1に定数10をセット
LC 2,3 ←レジスタ2に定数3をセット
MULT 1,(2) ←レジスタ1:2に乗算結果
LC 1,10 ←レジスタ1に定数10をセット
LC 2,3 ←レジスタ2に定数3をセット
LC 0,0 ←レジスタ0(被除数の上位16ビット)に定数0をセット
DIV 0,(2) ←レジスタ0とレジスタ1に余りと商を格納
※すべての命令において同様である。
ADD 1,2 ←レジスタ1に定数2を加算
ADD 1,(2) ←レジスタ1にレジスタ2を加算
ADD 1,3(2) ←レジスタ1にレジスタ2と定数3を加算
LC 1,300 ←レジスタ1に定数300をセットするつもり
実際は 300 % 256 = 44 (16進表記で 2C)が使われる
2012/4/27追記
例えば、
以下の通り、第2オペランドにレジスタ0を指定すると、レジスタ0の値を
無視して定数0が使用される。
レジスタ0以外の場合は期待通りにレジスタの値が使用される。
ADD 1,(0) ←レジスタ1に定数0を加算(レジスタ0ではない)
ADD 1,0(0) ←レジスタ1に定数0を加算(レジスタ0は無視)
ADD 1,2(0) ←レジスタ1に定数2を加算(レジスタ0は無視)
ADD 1,2 ←レジスタ1に定数2を加算
ADD 1,(2) ←レジスタ1にレジスタ2を加算(定数2ではない)
ADD 1,0(2) ←レジスタ1にレジスタ2と定数0を加算
ADD 1,3(2) ←レジスタ1にレジスタ2と定数3を加算
windowsの「電卓」アプリ(プログラマ電卓モード)を使って求めるとよい。3 => 0000 0000 0000 0011 (3を2進表現) => 1111 1111 1111 1100 (全ビット反転) => 1111 1111 1111 1101 (+1加算) => F F F D (-3の16進表現)
2012/4/27追記
使用例:
L 1,L1 ←ラベルL1のデータをレジスタ1に読み込む
LA 1,L1 ←ラベルL1のアドレスをレジスタ1にセットする
LC 1,9 ←定数 9をレジスタ1にセットする
LX 1,4(2) ←レジスタ2に定数4を足したアドレスからデータをレジスタ1に読み込む
LEA 1,4(2) ←レジスタ2に定数4を足したアドレスをレジスタ1にセットする
2012/5/1追記
※メモリ上にデータを置く作業をシミュレータのCHANGEコマンドを用いて行う他に、
機械語プログラムを使う方法もある。
マイクロプログラムを実行する前の初期設定を行う際に、
課題3で作った機械語プログラムをロードすれば、機械語プログラムと同じデータが
主記憶(MM)上に読み込まれる。
上記プログラムは
ラベル DATAから並んだ16個のデータの中から最大値を見つけ出すプログラムである。
計算結果(つまり最大値)をラベルRESULTの場所に格納する。
このプログラムにおいて、ループ処理により検索処理を行っている部分を
機械命令化することで、実行サイクル数が少なくすることができると考えられるので、
MICRO-1機械命令マイクロプログラム 'MICROONE'を元にして
検索処理命令を追加する。
追加する命令を機械語プログラムから使用する際には、EX命令を使う。
機械語プログラム中でEX命令を使う場合は、I型命令と同様の表記をする。
MICRO-1に追加する「最大値を求める命令」は Raで指定したレジスタにデータの先頭アドレス、NDにデータの個数を設定すると、 データを検索し、その最大値を求める。 求めた最大値を Rbで指定したレジスタに格納する。EX 1,16(2) ; (Ra部=2, Rb部=1, ND部=16)
最大値を求める命令を使った場合の機械語プログラムでは
元のプログラムのループ処理(データカウント処理部分)を1つの機械命令(EX命令)に
置き換えている。
このプログラムと
命令追加の変更を行った 'MICROONE'を組み合わせて実行する。
'MICROONE'中でEX命令を処理している部分を変更することで、最大値を求める追加命令を実現し、
シミュレータ上で実行せよ。
検索対象データの値(ラベル DATA以降に格納されている値)を変えて、
それぞれについて動作確認を行うこと。
また、課題4と同様に、元のプログラム(maxval)と実行ステップ数を比較して、
考察せよ。
実行ステップ数がどう変わったか?何故そうなるのか?を必ず説明すること。
注意1
'MICROONE'を修正するとその実行開始アドレス(デフォルトは101)も変わるため、
機械語プログラムを実行するときに指定する開始アドレスに注意する。
変更後の'MICROONE'の実行開始アドレスを調べるためには、
'MICROONE.M'の中身を調べてラベルINITのアドレス値を調べるとよい。
例えば、ラベルINITのアドレス値が 10Cであった場合は、マイクロプ
ログラムの実行開始アドレスも 10Cにすること。
※マイクロプログラム中の命令を追加あるいは削除した場合、このアドレス値も変化
するため、毎回確認すること。
注意2
マイクロプログラム 'MICROONE'の中ではレジスタの6番と7番はそれぞれ
サブルーチン呼び出し時の戻り先PC記録用のスタックポインタ、PUSH/POP命令で
レジスタ値の保存用のスタックポインタとして使われているため、値を勝手に
変更すると不具合を生じる。
またレジスタ0番から3番は機械語プログラムでも使用されるため、
これらのレジスタについても値を勝手に変更すると機械語プログラムが
正しく動作しなくなる。
もしこれらのレジスタを使いたい場合は、一旦レジスタの値をメモリ上に保存してから
使用すること。
また、レジスタを使用し終わったら、メモリ上に保存しておいた値をセットして
元の状態に戻すこと。
レジスタ4番と5番については自由に使うことができる。
レジスタ4番には命令レジスタIRのND部の値が格納されているので、必要に応じて
この値を使用することが出来る。
ヒント
'MICROONE'内の(ファイルの最後の方にある)ラベル EX0辺りから
EX命令用のマイクロ命令を記述すればよい。
処理の内容としては以下のようなことを記述すればよいと考えられる。
※番号のついた各項目がそれぞれ一つのマイクロ命令に対応している。
※上記とは別のやり方で求めても構わない。1. レジスタ4番(=命令レジスタND部の値が格納されている)の値をカウンタCにセット 2. もしカウンタCが0ならば(データが0個なので)ラベルEX3へ分岐 同時にレジスタRAの値をレジスタ5番にセット 3. メモリ読み出しサイクル開始 同時にレジスタ5番の値を+1し、カウンタCの値を1減らす 4. もしカウンタCが0ならば(データが0個なので)ラベルEX3へ分岐 同時にメモリから読み出した値をレジスタRBにセット EX1: 5. メモリ読み出しサイクル開始 同時にレジスタ5番の値を+1し、カウンタCの値を1減らす 6. メモリから読み出した値をレジスタ4番にセット 7. レジスタ4番の値とレジスタRBの値を比較 8. 比較結果がレジスタ4番の値がレジスタRBより小である場合ラベルEX2へ分岐 9. (最大値を更新するため)レジスタ4番の値をレジスタRBにセット ※常にレジスタRBに最大値が格納されるようにする EX2: 10. もしカウンタCの値が0であれば(すべて調べ終わったので)ラベルEX3へ分岐 11. ラベルEX1へ分岐(ループの先頭に戻る) EX3: 12. (これで命令の実行が終了なので)命令サイクルの最初に戻る
2012/5/7追記
ヒントにおける注意点
このフラグはカウンタCが0になると自動的に1がセットされるので、
SET
操作などを使って比較を行なう必要はない。
また、SET BY CやSET BY C-0という操作は記述できないので注意する。
例えば、MICROONE5 (9文字)などのファイル名は避ける。
※加算命令など他の命令の記述を参考にするとよい。
例えば、
メモリ上に配置された配列データの総和を求める命令、
2つのレジスタの最大公約数を求める命令、
主記憶上に配置したデータの先頭アドレスとサイズをレジスタオペランドとして
渡すと指定された領域を特定の値でクリアする命令、
データを暗号化する命令、
主記憶上に置いたデータをマイクロプログラムとみなして制御記憶に
読み込ませることで機械語プログラムからマイクロプログラムを書き換える命令、
等が考えられる。
また、課題2で使ったプログラムや課題3で作ったプログラムの一部の処理を
機械命令化するのでもよい。