分岐命令 プログラムの制御構造(C言語)

分岐命令
„ 条件判断(if 文)や繰返し(for 文,while 文)の制御構造
はどのようにつくるか
„ 制御構造を実現するための命令
• 分岐命令(条件分岐命令,無条件分岐命令)
• 比較命令
プログラムの制御構造(C言語)
条件判定: if - then - else 型
条件判定: if - then 型
条件
不成立
成立
条件
不成立
成立
命令列
命令列
1
1
命令列
2
プログラムの制御構造(C言語)
条件判定: do - while 型
繰返し: while 型
成立
条件
命令列
命令列
条件
成立
不成立
( for 文 はwhile型の特殊な場合 )
通常の実行では,実行した命令の次の番地(アドレス)の命令が
実行される
繰返しや条件判定などの制御構造を作るには,任意の番地に
分岐(ジャンプ)できる命令が必要になる
‹ 条件を判定し,条件の成立・不成立によって次に実行する命令
の番地を変更する命令
(条件分岐命令 / 条件ジャンプ命令)
: ただし条件によらず,「常に分岐 / ジャンプ」する命令(無条件分岐/
無条件ジャンプ命令)もある。
‹ 分岐 / ジャンプ先の番地を指定するにはラベル(label)を
用いる
2
ラベル(label)
ラベル: 命令やデータが配置されている主記憶上の番地
につけられた名前
1000 add
$s0, $s0, $s1
add
$s0, $s0, $s1
1004 addi
$s4, $zero, 1
addi
$s4, $zero, 1
1008 add
$s1, $s1, $s0
L1: add
$s1, $s1, $s0
1012 sub
$s0, $s0, $s4
sub
$s0, $s0, $s4
1016 bne
$s0, $s4, 1008
bne
$s0, $s4, L1
ラベル定義
ラベル参照
※ ラベルはアセンブラによって主記憶の番地に変換される
条件分岐命令(1)
一致(= 条件)分岐
beq $Ri,$Rj,Label
‹ “ branch on equal ”
‹ $Ri と $Rj が等しければ,ラベル Label に分岐
さもなければ,次のアドレスの命令を実行
…
beq $s1, $s0, L1
…
…
L1:
…
3
条件分岐命令(2)
不一致(≠ 条件)分岐
bne $Ri,$Rj,Label
‹ “ branch on not equal ”
‹ $Ri と $Rj が等しくなければ,ラベル Label に分岐
さもなければ,次のアドレスの命令を実行
…
bne $s1, $s0, L2
…
…
L2:
…
無条件分岐命令
無条件分岐
b Label
‹ “ branch ”
‹ 無条件で(常に),ラベル Label に分岐
…
b L3
…
…
L3:
…
4
条件: if - then型
C プログラム
1: if ( v == w ) {
2: x = x+1 ;
3: }
1
lw $s0, 0($gp)
# $s0 ← v
2
3
lw $s1, 4($gp)
bne $s0, $s1, exit
# $s1 ← w
4
lw $s3, 8($gp)
# $s0=$s1ならば,
5
6
addi $s3, $s3, 1
sw $s3, 8($gp)
# $s3 ← $s3 + 1
# $s0≠$s1 かどうか?
# x ← $s3
7 exit:
条件判定の扱い
プログラミング言語
: 成立したら次の文を実行
$gp
アセンブラ言語(機械語命令)
: 成立したら分岐する
v
w
→ アセンブラ言語では
逆の条件で調べたほうが
プログラム構造は考えやすい
x
条件: if - then - else 型
C プログラム
1: if ( v == w ) {
2: x = x+1 ;
3: } else {
4: x = x – 1;
5: }
$gp
v
w
x
# $s0 ← v
1
lw $s0, 0($gp)
2
3
4
5
lw $s1, 4($gp)
# $s1 ← w
bne $s0, $s1, else # $s0≠$s1かどうか?
lw $s2, 8($gp)
# $s2 ← x
addi $s2, $s2, 1
# $s2 ← $s2+1
6
sw $s2, 8($gp)
# x ← $s2
b exit
lw $s2, 8($gp)
addi $s2, $s2, -1
sw $s2, 8($gp)
# else 部をスキップ
7
8 else:
9
10
11 exit:
5
# $s2 ← x
# $s2 ← $s2 -1
# x ← $s2
分岐命令の命令形式
「現在のPCの値」は現在実行し
ている命令の次の命令の番地
になっていることに注意
※ 分岐先の番地は現在のPCの値からのオフセット(変位;何番地離れて
いるか)で指定する
命令の先頭番地は
(「何命令前か,何命令後か」 という指定形式:PC相対指定)
beq $Ri, $Rj, Label
op
rs
rt
address(offset)
000100
$Ri
$Rj
offset(2の補数表現)
31
PCの値はbeq命令の
次の命令の番地を指し
ているから
4番地ごとだから
26 25
21 20
0
16 15
{(Label の番地)– 4 –(この命令のある番地)}÷4
bne $Ri, $Rj, Label
op
rs
rt
000101
$Ri
$Rj
31
26 25
op
b Label
000100
31
21 20
rs
16 15
rt
00000
26 25
address(offset)
offset(2の補数表現)
00000
21 20
0
address(offset)
offset(2の補数表現)
16 15
0
b 命令は beq 命令で,$Ri=$Rj=$zero としたもの
( $zero=$zero だから常に成立)
分岐先アドレス(offset)の指定(後方の指定)
1000番地のbeq命令実行時
には,PCの値はすでに+4 さ
れている
31
904
0
lw $t0,0($t1)
(1104– 4 –1000)÷4 = 25
PC
PC+4
1000
1004
beq $s1,$s2,25
add $t0,$t1,$t2
1104
sub $t0,$t1,$t2
1104番地に
分岐しようと
する場合
分岐オフセット
100÷4=25
(25命令先)
次PC(分岐時)
分岐命令の次の命令から数えて(「現在のPCの値」が基準になることに
注意),25命令後(beq 命令の位置から数えると,26命令後方)
6
分岐先アドレス(offset)の指定(前方の指定)
31
次PC(分岐時)
分岐オフセット
-100÷4=-25
904
PC
PC+4
(25命令前)
0
lw $t0,0($t1)
1000
1004
beq $s1,$s2,-25
add $t0,$t1.$t2
1104
sub $t0,$t1,$t2
904番地に
分岐しようと
する場合
(904– 4 –1000)÷4 = -25
分岐命令の次の命令から数えて(「次の命令」の位置が基準になることに
注意),25命令前(beq 命令の位置から数えると,24命令前)
例
1200番地
beq $s0, $s1, L1
(ラベルL1は1264番地に対応するものとする)
op
rs
000100
31
rt
10000
26 25
address(offset)
0000000000001111
10001
21 20
16 15
0
分岐先は,このbeq命令の次の命令から15
命令先にあるので,オフセットは 15 となる
16進表記 : 1211000F
(1264-4-1200)/4=15 として計算できる
例
6400番地
bne $s0, $s1, L2
(ラベルL2は6144番地に対応するものとする)
op
rs
000101
31
rt
10000
26 25
address(offset)
1111111110111111
10001
21 20
16進表記 : 1611FFBF
16 15
0
分岐先は,このbeq命令の次の命令から65
命令前にあるので,オフセットは -65となる
(6144-4-6400)/4=-65 として計算できる
7