情報システム学実験2 ボードコンピュータ 2014年度 第5回 2014年11月6日 再帰呼び出し int { fact( int n) if (n < 1) return (1); else return (n * fact (n-1) ); } fact(3) 3 * fact(2) 2 * fact(1) 1 * fact(0) return(1) return(1*1) return(2*1*1) return(3*2*1*1) 例5-1:factorial関数 fact: L1: addi sw sw slt beq addi addi jr sub jal lw lw addi mul jr sp, sp, -8 ra, 4(sp) a0, 0(sp) t0, a0, 1 t0, zero, L1 v0, zero, 1 sp, sp, 8 ra a0, a0, 1 fact a0, 0(sp) ra, 4(sp) sp, sp, 8 v0, a0, v0 ra # スタックに2語をpush # raの退避 # a0(引数 n)の退避 # n < 1のテスト # if (n >= 1) goto L1 # 戻り値 <= 1 # スタックの2語をpop # return # a0 <= a0 - 1 # fact(n – 1)の再帰呼び出し # a0の復帰 # raの復帰 #スタックの2語をpop # 戻り値 <= n * fact(n -1) # return 関数を呼び出すとra、a0が上書きされるため、これをスタックに保存する 課題5-1 例5-1のプログラムfactを用いて、メインプログラムでコ ンソールから入力した整数に対して、fact関数を呼び出し て実行し、結果をコンソールに表示するようにせよ。また、 fact(5)を実行し、スタックに何が格納されるかを観察せよ。 コンソールの入出力例 Input a number : 5 factorial of 5 is 120 Input a number : をコンソールに出力する 入力された数値(1ケタ)から48を減ずる factを呼び出す factorial of x is y をコンソールに出力する スタックの観測方法 • RAMウィンドウの右クリックでJump to SPを 用いる 課題5-2 次の漸化式を計算するプログラムを再帰呼び出しを用 いて作成せよ。 an = an-1 + 2n - 1 a0 = 0 factorialのプログラムの一部を変更すれば容易にできる 入出力プログラミング (スイッチとLED) • Memory mapped I/O (メモリの特定番地を入 出力機器と対応させる) – 0xbf900000番地の書込み:LED出力 – 0xbf900000番地の読出し:スイッチ入力 • 1バイトなので、LB、LBU、SB命令を用いる 例5-2:スイッチからの入力を反転し、LED に出力する #include <iregdef.h> #define SWITCH 0xbf900000 .text .globl start .ent start start: la t1, SWITCH # SWITCH アドレスの設定 loop: lbu t0, 0(t1) # SWITCHの読み出し xori t2, t0, 0xff # 1byteの反転 sb t2, 0(t1) # LEDの書込み j loop .end start 課題5-3 コンソールから入力した1文字のASCIIコードをLEDに10回 点滅させるプログラムを作成せよ。点滅の速度はスイッチ 開始 で制御すること。 wait: beq addi j w1: jr a0, zero, w1 a0, a0, -1 wait ra count ←10 X←コンソール入力 N←スイッチ入力 XをLEDに出力 wait N 引数の回数だけループを回る 0をLEDに出力 wait N count-!=0 count:0 ==0 LBとLBUの違い LB (Load Byte)は符号拡張を行う。 LBU (Load Byte Unsigned)は符号拡張を行わない。 スイッチの値がFFのとき LA LB T1, SWITCH T2, 0(T1) T2=FFFFFFFF LA LBU T1, SWITCH T2, 0(T1) T2=000000FF 課題5.3でスイッチの値を読むときは、LBUの方がよい 入出力プログラミング (K1,K2ボタン) 0xBFA00000番地のビット 7 6 5 4 timer K1 K2 3 2 1 timer K1 0 K2 input only latched これを用いる K1を調べるには、 0xBFA00000番地 & 0x20 が0かどうかを見る K2を調べるには、 0xBFA00000番地 & 0x10 が0かどうかを見る 例5-3:K2ボタンを用いたポーリング(1) #include <iregdef.h> #define SWITCH 0xbf900000 #define INTERRUPT 0xbfa00000 .text .globl start .ent start start: jal wait # K2クリックのwait la s0, SWITCH # SWITCHアドレスの設定 lb s1, 0(s0) # SWITCHから最初の数のREAD jal wait # K2クリックのwait lb s2, 0(s0) # SWITCHから次の数のREAD add s3, s1, s2 # 加算 sb s3, 0x0(s0) # LEDへの書込み j start .end start スイッチに値を設定してから、K2を0→1→0と設定する 例5-3:K2ボタンを用いたポーリング(2) wait関数:K2が0→1→0となるのを待つ .ent wait wait: la L1: lb andi beq L2: sb lb andi bne jr .end L1 t0, INTERRUPT t1, 0(t0) t2, t1, 0x10 t2,zero, L1 zero, 0(t0) t1, 0(t0) t2, t1, 0x10 t2,zero, L2 ra wait K2のbit位置は0x10 INTERRUPTの読み出し =0 終了検査 !=0 L2 INTERRUPTの読み出し !=0 終了検査 =0 課題5-4 プログラム起動時にスイッチの値を読み出してLEDに出 力し、K1が押されたときインクリメントしてLEDに出力し、 K2が押されたときその値をデクリメントしてLEDに出力す るプログラムを作成せよ。 start関数 Switchの読出し LEDに出力 K1かK2をwait K1? != = = K2? != Decrement LEDに出力 Increment LEDに出力 課題5-4 (wait関数) INTERRUPTの読み出し 終了検査でK1、K2の両方を待つ 0x30とのANDをとればよい =0 K1、K2のいずれが押されたかを 示すための戻り値が必要 終了検査 !=0 INTERRUPTの読み出し !=0 終了検査 =0 進捗確認 ① ② ③ ④ 課題5-1の動作(TA確認) 課題5-2の動作(TA確認) 課題5-3の動作(TA確認) 課題5-4の動作(TA確認)
© Copyright 2024 ExpyDoc