制御の流れ
(分岐命令)
プロセッサの基本構成要素
PCの指す番地から取
得した命令を保持
次に実行する命
令の番地を記憶
プロセッサ
命令レジスタ
命令レジスタの内
容(取得した命令)
を解読
PC
デコーダ
ALU
算術演算や論
理演算を実行
プログラムの命令
とデータを格納.
レジスタ
・
・
・
主記憶
ALUで計算される
データを記憶
PC: Program Counter
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
アドレス
PC
0x00104
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
PCの指す番地から取
得した命令を保持 プロセッサ
命令レジスタ
add $t0, $s1, $s2
実行する命令の
アドレス
アドレス
PC
0x00104
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
add $t0, $s1, $s2
次命令の取得にそ
なえてPCを更新
アドレス
PC
0x00108
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
add $t0, $s1, $s2
アドレス
PC
0x00108
デコーダ
ALU
取得した命令を解読
(s1とs2を加算し,t0へ格納)
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
add $t0, $s1, $s2
アドレス
PC
0x00108
デコーダ
加算
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
PCの指す番地から取
得した命令を保持 プロセッサ
命令レジスタ
sub $t1, $t0, $s3
実行する命令の
アドレス
アドレス
PC
0x00108
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
sub $t1, $t0, $s3
次命令の取得にそ
なえてPCを更新
アドレス
PC
0x0010c
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
sub $t1, $t0, $s3
アドレス
PC
0x0010c
デコーダ
ALU
取得した命令を解読
(t0とs3を減算し,t1へ格納)
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
プロセッサ
命令レジスタ
sub $t1, $t0, $s3
アドレス
PC
0x0010c
デコーダ
減算
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
主記憶
・・・
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
命令の実行手順
PCの指す番地から取
得した命令を保持 プロセッサ
命令レジスタ
lw $t1, 320($s4)
実行する命令の
アドレス
PC
0x0010c
・・・
デコーダ
ALU
主記憶
アドレス
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
0x00104
add $t0, $s1, $s2
0x00108
sub $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
2.命令の解読:命令レジスタの値をデコード
3.命令の実行:解読結果に従って実行
以降,繰り返し・・・
九州大学工学部電気情報工学科
逐次制御だけで十分なのか?
命令実行に関する基本動作
主記憶に格納された命令を1個ずつ,順番に実行する(逐次制御)
全ての場合に対応できるのだろうか?
A[80] = (g + A[2]) – (h + A[i]);
lw $t0, 8 ($s4)
add $t0, $t0, $s1
add $t1, $s3, $s3
add $t1, $t1, $t1
add $t1, $t1, $s4
lw $t1, 0 ($t1)
add $t1, $t1, $s2
sub $t1, $t0, $t1
sw $t1, 320 ($s4)
逐次制御で問題なし!
if (i == j)
f = g + h;
else
f = g – h;
???
逐次制御だけでは対応できない!
条件に応じて分岐する必要がある!
九州大学工学部電気情報工学科
MIPSの命令(一部)
命令
命令区分
算術演算 add
データ転
送
意味
add $s1, $s2, $s3
$s1 = $s2 + $s3
Subtract
sub $s1, $s2, $s3
$s1 = $s2 – $s3
load word
lw $s1, 100($s2)
$s1に,メモリの[$s2+100]番地の
ワードデータを読込み
store word
sw $s1, 100($s2)
メモリの[$s2+100]番地に,$s1の
ワードデータを書込み
beq $s1, $s2, L
もし、$s1==$s2ならLへ分岐
branch on not
equal
bne $s1, $s2, L
もし、$s1!=$s2ならLへ分岐
set on less than
slt $s1, $s2, $s3
もし、$s2<$s3なら$s1=1, 以外なら
$s1=0
jump
jL
Lにジャンプ
jump register
jr $s1
$s1の値が示すアドレスにジャンプ
条件分岐 branch on equal
無条件
ジャンプ
例
$s1~$s3は汎用レジスタ
九州大学工学部電気情報工学科
ラベル名
ラベル名: 命令やデータが配置されている主記憶上の番地につけ
られた名前.
100
add
$s0, $s0, $s1
add
$s0, $s0, $s1
104
addi
$s4, $zero, 1
addi
$s4, $zero, 1
108
add
$s1, $s1, $s0
add
$s1, $s1, $s0
112
sub
$s0, $s0, $s4
sub
$s0, $s0, $s4
116
bne
$s0, $s4, 108番地
bne
$s0, $s4, L1
L1:
ラベル定義
ラベル参照
ラベル名はアセンブラによって実際の番地に変換される.
九州大学工学部電気情報工学科
条件分岐命令(1)
条件分岐命令がない場合
①
②
③
④
add $s1, $s2, $s3
add $t0, $s1, $s4
lw $t1, 8 ($s5)
sub $t1, $t1, $t0
命令実行の流れ
条件分岐命令がある場合
① add $s1, $s2, $s3
② beq $s1, $s6, GoTo
add $t0, $s2, $s4
sw $t0, 8 ($s5)
①
②
③
④
GoTo:
③ add $s4, $t4, $t3
④ sw $s4, 8 ($s5)
②で分岐条件が成立
した場合
分岐条件が不成立
の場合
九州大学工学部電気情報工学科
条件分岐命令(2)
例)
beq $s0, $s1, L1
レジスタ$s0の値と$s1の値を比
較して,同じであればラベルL1
へ分岐(PCの値を設定)
beq: Branch on EQual
bne $s0, $s1, L1
beq
$s0, $s1, L1
$s0 = $s1
Yes
No
次の命令
bne
ラベルL1の番地
$s0, $s1, L1
レジスタ$s0の値と$s1の値を比
較して,同じでなければラベル
L1へ分岐(PCの値を設定)
$s0 $s1
bne: Branch on Not Equal
次の命令
Yes
No
ラベルL1の番地
九州大学工学部電気情報工学科
条件分岐命令(3)
プロセッサ
命令レジスタ
アドレス
PC
0x00104
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
PCの指す番地から取
得した命令を保持 プロセッサ
命令レジスタ
beq $t0, $s1, L1
実行する命令の
アドレス
アドレス
PC
0x00104
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
プロセッサ
命令レジスタ
beq $t0, $s1, L1
次命令の取得にそ
なえてPCを更新
アドレス
PC
0x00108
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
プロセッサ
命令レジスタ
beq $t0, $s1, L1
アドレス
PC
0x00108
デコーダ
取得した命令を解読
ALU
(t0==s1ならL1へ分岐)
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
プロセッサ
命令レジスタ
beq $t0, $s1, L1
比較
デコーダ
(結果は一致!)
ALU
アドレス
PC
0x00108
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
プロセッサ
分岐先アドレスに更新!
命令レジスタ
アドレス
beq $t0, $s1, L1
PC
比較
デコーダ
(結果は一致!)
ALU
0x00400
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(3)
PCの指す番地から取
得した命令を保持 プロセッサ
命令レジスタ
lw $t1, 120($s4)
実行する命令の
アドレス
アドレス
PC
0x00400
デコーダ
ALU
レジスタ
1.命令の取得:PCが指すアドレスの値をメモリ
から命令レジスタへ取得.同時に,次命令の
取得に備えてPCの値を更新(例えば+4)
2.命令の解読:命令レジスタの値をデコード
主記憶
・・・
0x00104
beq $t0, $s1, L1
0x00108
add $t1, $t0, $s3
0x0010c
lw $t1, 320($s4)
L1
・・・
0x00400
lw $t1, 120($s4)
・・・
実際には,各命令は2進表現
でメモリに格納されている
3.命令の実行:解読結果に従って実行
九州大学工学部電気情報工学科
条件分岐命令(4)
例)
slt $s0, $s1, $s2
レジスタ$s1の値と$s2の値を比較
して,$s1<$s2であれば$s0に値
「1」を,そうでなければ値「0」を格
納(分岐条件の設定に利用)
slt: Set on Less Than
Yes
$s0 ← 1
$s1 < $s2
No
$s0 ← 0
九州大学工学部電気情報工学科
無条件分岐命令(1)
分岐命令がない場合
①
②
③
④
add $s1, $s2, $s3
add $t0, $s1, $s4
lw $t1, 8 ($s5)
sub $t1, $t1, $t0
命令実行の流れ
無条件分岐命令がある場合
① add $s1, $s2, $s3
② j GoTo
add $t0, $s2, $s4
sw $t0, 8 ($s5)
GoTo:
③ add $s4, $t4, $t3
④ sw $s4, 8 ($s5)
常に分岐先を実行
九州大学工学部電気情報工学科
無条件分岐命令(2)
例)
j L1
常にラベルL1へ分岐(PCの値
を設定)
j: Jump
jr $s0
常に$s0に格納されている番地
へ分岐(PCの値を設定)
jr: Jump Register
九州大学工学部電気情報工学科
アセンブリ言語プログラムを書いてみよう!
問題:以下,4つの場合に関して,slt命令,beq命令,または,
bne命令を用いてアセンブリ言語プログラムを作成せよ.な
お,常にゼロの値を保持するレジスタ($zero)を用いて良い.
①「$s0 < $s1」 ならラベルLへ分岐
②「$s0 > $s1」 ならラベルLへ分岐
③「$s0 <= $s1」 ならラベルLへ分岐
④「$s0 >= $s1」 ならラベルLへ分岐
九州大学工学部電気情報工学科
アセンブリ言語プログラムを書いてみよう!
問題:以下,4つの場合に関して,slt命令,beq命令,または,
bne命令を用いてアセンブリ言語プログラムを作成せよ.な
お,常にゼロの値を保持するレジスタ($zero)を用いて良い.
①「$s0 < $s1」 ならラベルLへ分岐
②「$s0 > $s1」 ならラベルLへ分岐
③「$s0 <= $s1」 ならラベルLへ分岐
④「$s0 >= $s1」 ならラベルLへ分岐
解答①
$s0<$s1なら$t0←1,そ
れ以外なら$t0←0
slt
bne
$t0, $s0, $s1
$t0, $zero, L
$t0≠$Zero(つまり$t0=1)な
らLへ分岐
$s1<$s0なら$t0←1,そ
れ以外なら$t0←0
slt
bne
解答②
$t0, $s1, $s0
$t0, $zero, L
$t0≠$Zero(つまり$t0=1)な
らLへ分岐
九州大学工学部電気情報工学科
アセンブリ言語プログラムを書いてみよう!
問題:以下,4つの場合に関して,slt命令,beq命令,または,
bne命令を用いてアセンブリ言語プログラムを作成せよ.な
お,常にゼロの値を保持するレジスタ($zero)を用いて良い.
①「$s0 < $s1」 ならラベルLへ分岐
②「$s0 > $s1」 ならラベルLへ分岐
③「$s0 <= $s1」 ならラベルLへ分岐 ⇒$s0>$s1でない
④「$s0 >= $s1」 ならラベルLへ分岐 ⇒$s0<$s1でない
解答③
$s1<$s0なら$t0←1,
それ以外なら$t0←0
slt
beq
$t0, $s1, $s0
$t0, $zero, L
$t0=$Zero(つまり$t0=0)
ならLへ分岐
$s0<$s1なら$t0←1,
それ以外なら$t0←0
slt
beq
$t0, $s0, $s1
$t0, $zero, L
解答④
$t0=$Zero(つまり$t0=0 )な
らLへ分岐
九州大学工学部電気情報工学科
コード例: C言語の goto 文
ラベル名で指定するところに飛ぶ.
L100:
…
goto L100;
...
xxxx
L100:
j
…
xxxx
L100
九州大学工学部電気情報工学科
コード例: C言語の if 文(1)
式の値が真(0以外の整数)ならば else の前を実行する.式の
値が偽(0)ならば else の後を実行する.文が複数ある場合は
中括弧でくくる.
if (式)
文;
else
文;
省略可能
if (式) {
文;
...
}
else {
文;
...
}
式の値が偽のときに特にすることがなければ,else 以降は省
略してもよい.
九州大学工学部電気情報工学科
コード例: C言語の if 文(2)
L1:
L1:
if (i == j) goto L1;
f = g + h;
f = f – i;
beq
add
sub
$s3, $s4, L1
$s0, $s1, $s2
$s0, $s0, $s3
変数名
レジスタ
f
$s0
g
$s1
h
$s2
i
$s3
j
$s4
九州大学工学部電気情報工学科
コード例: C言語の if 文(3)
if (i == j)
f = g + h;
else
f = g – h;
ELSE:
EXIT:
bne
add
j
sub
…
$s3, $s4, ELSE
$s0, $s1, $s2
EXIT
$s0, $s1, $s2
変数名
レジスタ
f
$s0
g
$s1
h
$s2
i
$s3
j
$s4
九州大学工学部電気情報工学科
コード例: C言語の while 文(1)
1. 条件式を評価する.
2. 条件式の値が真(0以外の整数)ならば文または中括弧の中
を実行する.偽(0)ならば文または中括弧の中を実行せずに
次に進む(=ループを終了する).
3. 文または中括弧の中を実行した後は 1. に戻る.
while (条件式)
文;
while (条件式) {
文;
...
}
条件式が「真」の間,
繰り返し実行される
九州大学工学部電気情報工学科
コード例: C言語の while 文(2)
while (save[i] == k)
i = i + j;
save[i] の番地 = $s6 + $s3 * 4
WHILE:
EXIT:
add
add
add
lw
bne
add
j
…
$t0, $s3, $s3
$t0, $t0, $t0
$t0, $t0, $s6
$t1, 0($t0)
$t1, $s5, EXIT
$s3, $s3, $s4
WHILE
変数名
レジスタ
i
$s3
j
$s4
k
$s5
save[] 先頭番地
$s6
九州大学工学部電気情報工学科
コード例: C言語の switch 文(1)
式の値と同じ値の case のところに飛ぶ.該当する case がな
い場合は default のところに飛ぶ.
switch (式) {
case 値1:
...
case 値2:
...
case 値3:
...
default:
...
}
式=値1のとき
式=値2のとき
式=値3のとき
式=その他の値のとき
省略可能
default 以降は不要ならば省略してもよい.
九州大学工学部電気情報工学科
コード例: C言語の switch 文(2)
通常,switch 文の各 case のあとには break 文を入れる.
switch 文の中括弧の中で break 文を実行すると,中括弧の残
りの実行を打ち切り,switch 文の外に飛ぶ.
switch (式) {
case 値1:
...
break;
case 値2:
...
break;
default:
...
}
式=値1のとき
式=値2のとき
式=その他の値のとき
九州大学工学部電気情報工学科
コード例: C言語の switch 文(3)
switch (k) {
case 0:
f = i + j;
break;
case 1:
f = g + h;
break;
case 2:
f = g – h;
break;
case 3:
f = i – j;
break;
}
•kが「0」の場合
• f=i+j;だけが実行される
•kが「1」の場合
• f=g+h;だけが実行される
•kが「2」の場合
• f=g-h;だけが実行される
•kが「3」の場合
• f=i-j;だけが実行される
•kが「0,1,2,3以外の場合」
• switch本体は実行されない
九州大学工学部電気情報工学科
コード例: C言語の switch 文(4)
k == 0
Yes
f←i+j
No
k == 1
Yes
f←g+h
No
k == 2
Yes
f←g–h
No
k == 3
時間が
かかる!!
No
Yes
f←i–j
九州大学工学部電気情報工学科
コード例: C言語の switch 文(5)
表に登録されている
番地に分岐.
添え字
登録番地
0
L0
1
L1
2
L2
3
L3
k
k == 0
k == 1
k == 2
k == 3
L0: f ← i + j
L1: f ← g + h
L2: f ← g – h
L3: f ← i – j
九州大学工学部電気情報工学科
コード例: C言語の switch 文(6)
範囲検査
多岐分岐
L0:
L1:
L2:
L3:
EXIT:
slt
bne
slt
beq
add
add
add
lw
jr
add
j
add
j
sub
j
sub
…
$t3, $s5, $zero
$t3, $zero, EXIT
$t3, $s5, $t2
$t3, $zero, EXIT
$t0, $s5, $s5
$t0, $t0, $t0
$t0, $s6, $t0
$t1, 0($t0)
$t1
$s0, $s3, $s4
EXIT
$s0, $s1, $s2
EXIT
$s6 →
$s0, $s1, $s2
EXIT
$s0, $s3, $s4
変数名
レジスタ
f
$s0
g
$s1
h
$s2
i
$s3
j
$s4
k
$s5
番地表先頭番地
$s6
定数4
$t2
添え字
登録番地
0
L0
1
L1
2
L2
3
L3
九州大学工学部電気情報工学科
コード例: C言語の for 文(1)
1. 初期化式を評価する.
2. 条件式の値が真(0以外の整数)ならば文または中括弧の中
を実行する.偽(0)ならば文または中括弧の中を実行せずに
次に進む(=ループを終了する).
3. 文または中括弧の中を実行した後は,更新式を評価し,2. に
戻る.
for (初期化式; 条件式; 更新式)
文;
条件式が「真」の間,
繰り返し実行される
for (初期化式; 条件式; 更新式) {
文;
...
}
九州大学工学部電気情報工学科
コード例: C言語の for 文(2)
for (i = 0, j = 15; i < j; i++, j--) {
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
i
j
a[0]
a[1]
a[2]
a[14]
a[15]
九州大学工学部電気情報工学科
コード例: C言語の for 文(3)
初期化式
条件式 FOR:
tmp = a[i]
a[i] = a[j]
a[j] = tmp
更新式
EXIT:
add
add
slt
beq
add
add
add
lw
add
add
add
lw
sw
sw
add
sub
j
…
$s0, $zero, $zero
$s1, $t4, $zero
$t0, $s0, $s1
$t0, $zero, EXIT
$t1, $s0, $s0
$t1, $t1, $t1
$t1, $s3, $t1
$s2, 0($t1)
$t2, $s1, $s1
$t2, $t2, $t2
$t2, $s3, $t2
$t3, 0($t2)
$t3, 0($t1)
$s2, 0($t2)
$s0, $s0, $t5
$s1, $s1, $t5
FOR
変数名
レジスタ
i
$s0
j
$s1
tmp
$s2
a[] 先頭番地
$s3
定数15
$t4
定数1
$t5
九州大学工学部電気情報工学科
制御の流れ
(手続き呼出)
手続き呼出の基本(1)
#include <stdio.h>
int add (int a, int b)
{
int c;
3, 4
a + b を計算して
c に代入
7
c の値を返す
関数 add 呼出
c に結果代入
c = a + b;
return c;
c: 7, d: 0
c, d の値を表示
}
int main ()
{
int c = 0, d = 0;
c: 7, d: 16
c = add (3, 4);
printf (”c: %d, d: %d\n”, c, d);
d = add (c * 2, 2);
printf (”c: %d, d: %d\n”, c, d);
…
}
関数 add
14, 2
a + b を計算して
c に代入
16
c の値を返す
関数 add 呼出
d に結果代入
関数 add
c, d の値を表示
caller
callee
九州大学工学部電気情報工学科
手続き呼出の基本(2)
#include <stdio.h>
callee の作業:
int add (int a , int b)
{
int c;
1.
2.
3.
c = a + b;
return c;
仮引数
caller の作業:
}
int main ()
{
int c = 0, d = 0;
実引数
c = add (3 , 4);
printf (”c: %d, d: %d\n”, c, d);
d = add (c * 2 , 2);
printf (”c: %d, d: %d\n”, c, d);
…
}
実引数の仮引数への代入.
内部の実行.
復帰: caller へのジャンプ.
1.
2.
3.
実引数式の値の計算.
呼出: callee へのジャンプ.
結果の受け取り.
caller は複数ありうるので単純
なジャンプでは caller へ復帰で
きない.
九州大学工学部電気情報工学科
手続き呼出の基本(3)
実引数の受け渡し: レジスタ $a0~$a3 (レジスタ番号 4~7)
を使用.
結果の受け取り: レジスタ $v0,$v1(レジスタ番号 2,3)を使
用.
callee へのジャンプ: jal 命令を使用.
caller へのジャンプ: jr 命令を使用.
jal 命令: レジスタ $ra(レジスタ番号 31)に jal 命令直後の命令
の番地(= PC + 4)を格納し,ラベルで指定される callee へジャン
プ.復帰時は jr 命令で $ra が格納する番地にジャンプ.
jal
jr
callee
$ra
# callee 呼出
# caller へ復帰
九州大学工学部電気情報工学科
手続き呼出の基本(4)
caller 側のコード
int main ()
{
…
c = add (3, 4);
…
d = add (c * 2, 2);
…
}
変数名
レジスタ
c
$s0
d
$s1
…
addi
addi
jal
add
…
add
addi
jal
add
…
第一実引数
$a0, $zero, 3
$a1, $zero, 4
_add
$s0, $v0, $zero
第二実引数
返り値
$a0, $s0, $s0
$a1, $zero, 2
_add
$s1, $v0, $zero
【注意】addi 命令は,レジスタと定数値を加算して,その結果をレジスタに格納
する命令である.(後述)
九州大学工学部電気情報工学科
手続き呼出の基本(5)
callee 側のコード
int add (int a , int b)
{
int c;
_add:
add
add
jr
c = a + b;
return c;
第一仮引数
$s0, $a0, $a1
$v0, $s0, $zero
$ra
第二仮引数
返り値
復帰先番地
}
変数名
レジスタ
c
$s0
caller が,呼出前に復帰先番地を $ra に設定していることに注意すること.
九州大学工学部電気情報工学科
手続き呼出とスタック(1)
int add (int a, int b)
{
return a + b;
}
$ra が上書きされ
る.(=main に戻れ
ない!)
int dbl (int a)
{
int c;
c = add (a, a);
return c;
}
int main ()
{
int c;
…
c = dbl (100);
foo (a, 3, b, 4, c);
…
}
_add:
add
jr
_dbl:
add
caller で使ってい
たレジスタが上書き
される.
引数が4つ以
上ある場合は?
$v0, $a0, $a1
$ra
add
jal
add
jr
_main:
…
addi
jal
add
…
#add 第一実引数
$a0, $a0, $zero
#add 第二実引数
$a1, $a0, $zero
_add
$s0, $v0, $zero
$ra
$a0, $zero, 100
_dbl
$s0, $v0, $zero
九州大学工学部電気情報工学科
手続き呼出とスタック(2)
MIPS のレジスタ使用に関するルール(=紳士協定!)
レジスタ名
レジスタ番号
用途
$zero
0
$v0~$v1
2~3
関数の返り値
$a0~$a3
4~7
引数用
$t0~$t7
8~15
一時保存用
$s0~$s7
16~23
変数用
$t8~$t9
24~25
一時保存用
$sp
29
スタックポインタ(後述)
不可
$fp
30
フレームポインタ(後述)
不可
$ra
31
戻り番地
不可
定数値 0,不要な結果の破棄
関数呼出時のレジスタ破壊
(NA)
可
不可
可
不可
可
関数呼出時のレジスタ破壊が「不可」のレジスタは,関数呼出直前と復帰直後
の値が同じになることを,プログラマが保証しなければならない.
九州大学工学部電気情報工学科
手続き呼出とスタック(3)
上書き問題の解決策 = スタックの利用
スタック: 他のデータを後入れ先出し型(LIFO: Last-In First-Out)
で格納するデータ構造.データの追加(push),データの取り出し
(pop),最後に格納したデータの参照(top)のみが許される.
push 5
push 7
3
5
7
5
7
7
pop
push 3
pop
pop
九州大学工学部電気情報工学科
手続き呼出とスタック(4)
MIPS におけるスタック:
メモリ領域の一部をスタックのために使用する.
MIPS では,29番のレジスタに $sp と名前をつけ,スタックの一
番上の番地を記憶するために使用する.(スタックポインタ)
$sp
112
100
104
108
112
$sp
108
–4
+4
push yyyy
xxxx
xxxx
100
104
108
112
116
yyyy
xxxx
xxxx
pop
九州大学工学部電気情報工学科
手続き呼出とスタック(5)
手続き foo の呼出手順(不完全版):
1.
2.
3.
4.
関数呼出によって破壊されうるレジスタ($t0~$t9,$v0,$v1)
の値を push する.(後に参照するレジスタのみでよい.)
foo を呼び出す.(jal foo 命令)
foo の内部で他の関数を呼び出す場合は $ra を push する.
関数呼出によって破壊されてはならないレジスタ($a0~$a3,
$s0~$s7)の値を push する.(foo 内部で更新するレジスタの
みでよい.)
caller
callee
手続き foo からの復帰手順(不完全版):
1.
2.
3.
4.
呼出後 4 で push した値を元のレジスタに pop する.
呼出後 3 で $ra を push した場合は,その値を $ra に pop す
る.
foo を呼び出した jal 命令の次の命令にジャンプする.(jr $ra
命令)
呼出前 1 で push した値を元のレジスタに pop する.
callee
caller
九州大学工学部電気情報工学科
手続き呼出とスタック(6)
int foo (int a, int b, int c, int d, int e, int f)
{
int g, h;
…
}
スタック
$a0~$a3
… = foo (3, 8, 2, 5, 4, 6);
手続き foo の呼出手順(完全版):
1.
2.
3.
4.
5.
6.
7.
$sp
ローカル変数
(g, h)
callee 側
レジスタ保存
$ra 保存
caller 側
レジスタ保存
5番目以降の実引数を push
フレームポインタ 第5実引数(4)
caller 側レジスタ保存($t0~$t7 etc.)
第6実引数(6)
$fp
foo 呼出
$ra を push
手続きフレーム
callee 側レジスタ保存($s0~$s9 etc.)
ローカル変数のための領域をスタック上に確保
$fp をスタックフレームの底に設定.
九州大学工学部電気情報工学科
手続き呼出とスタック(7)
手続きフレームは,関数の呼出ごとに生成される.
int bar ()
{
…
}
int foo ()
{
int x, y;
…
bar ();
…
foo ();
…
}
foo () 1回目
foo () 2回目
bar ()
bar ()
foo ()
bar ()
foo ()
foo ()
foo ()
foo ()
foo ()
呼出ごとに独立したローカル変数の実現.
再帰呼出が可能.
九州大学工学部電気情報工学科
Created by Tsuneo Nakanishi, 2002-2004 (R1.00)
Updated by Koji Inoue, 2005 (R1.01)
Updated by Koji Inoue, 2005 (R1.02)
九州大学工学部電気情報工学科
© Copyright 2026 ExpyDoc