5週目スライド

情報システム学実験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確認)