as-4. 条件分岐と繰り返し
1
金子邦彦
(68000アセンブラプログラミング)
URL: https://www.kkaneko.jp/cc/as/index.html
条件分岐とは
Yes
No
B A
条件
• 「ある条件」が成り立てばAを、成り立たな
ければBを実行
例題1.2数の最大値
• データレジスタ D0, データレジスタ D1 のう
ち大きい方をデータレジスタ D2 にセットす
る
例) D0 の中身: 0x 0000 0030
D1 の中身: 0x 0000 0040
のとき
D2 の中身: 0x 0000 0040
.text
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
move.l %d0,%d2
bra ENDIF1
ELSE1:
move.l %d1,%d2
ENDIF1:
.dc.w 0x4848
stop #0
.end
条件が成り立つ場合に
実行される部分
条件分岐命令
条件が成り立たない場合
に実行される部分
比較命令 (D0 と D1 の比較)
.text
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
move.l %d0,%d2
bra ENDIF1
ELSE1:
move.l %d1,%d2
ENDIF1:
.dc.w 0x4848
stop #0
.end
実行順
「D1 の中身 > D0 の中身」が成り立つ場合
①
②
③
④
⑤
.text
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
move.l %d0,%d2
bra ENDIF1
ELSE1:
move.l %d1,%d2
ENDIF1:
.dc.w 0x4848
stop #0
.end
実行順
「D1 の中身 > D0 の中身」が成り立たない場合
①
②
③
④
⑤
⑥
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
条件分岐の一般形
<コンディションコードレジスタを変化させる命令>
<条件分岐命令>
cmp など
bhi, bcc, beq
bne, bcs, bls など
D0, D1 の中身を比較.
比較結果による条件分岐
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
条件分岐命令
分岐する条件
bhi
D0の中身 < D1の中身
bcc
D0の中身 ≦ D1の中身
beq
D0の中身 = D1の中身
bne
D0の中身 ≠ D1の中身
bcs
D0の中身 > D1の中身
bls
D0の中身 ≧ D1の中身
cmp.l %d0,%d1
bhi ELSE1 /* d1 > d0 */
分岐条件
bhi, bcc, beq
bne, bcs, bls など
分岐先の
メモリアドレス
※ プログラムカウンタ
にセットされる
例題2.条件分岐
• 条件分岐の例として,次の例を考える
)5( 0
)5( 8
のとき
のとき
=
=
xy
xxy
(一部の内容は,復習を兼ねる)
ロングワード
1ロングワードは4バイト
それぞれ、1ロングワードの
データエリアをメモリ中に確保
プログラム中で使用
.1 ロングワード(4バイト)
.w ワード(2バイト)
.b バイト(1バイト)
x と 5 の比較
(D0 を使用)
x > 5 のとき実行
される部分
x > 5 が成り立たない
とき実行される部分
比較結果による分岐
実行順
①
②
③
④
⑤
⑥
⑦
⑧
以後省略
ジャンプ
分岐命令
ラベル endif1 へ
分岐せよという指示
※ bra は必ず分岐する
x > 5 のとき実
行される部分
もし x>5 ならば
分岐しない
スキップ
①
②
③
④
⑤
以後省略
ジャンプ
ラベル else1へ分岐
せよという指示
実行順
もし x≦5 ならば
x>5 が成り立たないとき
実行される部分
分岐する
スキップ
moveq.l #5,%d0
cmp.l x,%d0
bcc else1
D0 に 0x0000 0005 を入れる
x の中身と D0 の比較
※ メモリからの読み出し
※ D0 を比較のために使用
5(数値)と X の中身を比較.
比較結果による条件分岐
moveq.l #5,%d0
cmp.l x,%d0
bcc else1
この場合の意味
bhi xの中身 < D0の中身
bcc xの中身 ≦ D0の中身
beq xの中身 = D0の中身
bne xの中身 ≠ D0の中身
bcs xの中身 > D0の中身
bls xの中身 ≧ D0の中身
分岐条件
bhi
bcc
beq
bne
bcs
bls
条件分岐条件
D0 に 0x0000 0005 を入れる
x の中身と D0 の比較
(メモリからの読み出し)
cmp.l x,%d0
bcc else1
条件分岐の一般形
<コンディションコードレジスタを変化させる命令>
<条件分岐命令>
cmp など
bhi, bcc, beq
bne, bcs, bls など
5(数値)と X の中身を比較.
比較結果による条件分岐
算術演算ユニット
Arithmetic and Logic Unit
00000005
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
引き算の結果が,0
か正か負かによって
CCRの値が定まる
「cmp.l x,%d0」の実行では
D0
xの中身
00000005
x
「引き算」が
実行される
アドレスバス
データバス
制御系
Control Unit
+命令長
R/W
「bcc else1」の実行では
プログラムカウンタ
Program Counter
メモリ
CCR の値が
「引き算の結果が正または0」を示
すときにのみ,プログラムカウンタ
に新しい値が入る
→ 分岐
ステータスレジスタ
S
I0
I1
I2
C
V
Z
X
N
13 10 9 8 4 3 2 1 0
?
?
?
?
?
?
?
?
?
CCR
ステータスレジスタ(16ビット)
の下位1バイトが,コンディション
コードレジスタ(CCR)
コンディションコードレジスタの
フラグの振る舞い
• フラグは X, N, Z, V, C の5つ
• フラグはすべて1ビット(0か1の値をとる)
cmp 命令での振る舞い
cmp.l <ソース>, <ディスティネーション>
2つの比較
Nフラグ: <ディスティネーション>ー<ソース> < 0 なら1
さもなければ0
Zフラグ: <ディスティネーション>ー<ソース> = 0 なら1
さもなければ0
※ cmp 命令以外でも CCR の値は変化する
2数の引き算の結果
(参考)MOVE 命令でのコンディ
ションコードレジスタの変化
X: 変化せず
N: 転送結果の「最上位ビット」が1ならセット(1)、
それ以外はリセット(0)
Z: 転送結果が「全てのビット」が0ならセット(1)、
それ以外はリセット(0)
V: 常にリセット(0)
C: 常にリセット(0)
※ 2つの比較ではなく、
「転送したデータ」の値に
よる変化
例題3.繰り返し
• 次の例で、条件分岐命令を見る
=
=
3
1i
is
繰り返しの一般形
• 何かの処理の繰り返し
• 繰り返しのたびに 条件分岐命令が実行さ
れ, 指定された条件が成り立たない限り,
実行が繰り返される
条件
X
No
Yes
START:
命令(比較命令,演算など)
b?? QUIT
命令
命令
…
bra START
QUIT:
繰り返し
繰り返しの終了条件
「D0 の中身 <= 3」が成り立たない
D0 の中身
と 3 の比較
D0 の中身 > 3
のときはジャンプ
分岐条件
bhi D0 > 3
bcc D0 >= 3
beq D0 = 3
bne D0 != 3
bcs D0 < 3
bls D0 <= 3
D0 の中身≦ 3
のとき
繰り返し
ジャンプ
繰り返しを続ける
D0 の中身
と 3 の比較
例題4.ワードデータの配列
• 10個のワードデータに,順に,0000, 0001,
0002, ・・・, 0009 をセットするプログラム
実行前
10ワード(=20バイト)
のデータエリア
プログラム本体そのものが
入っているエリア
未使用
実行後
10ワード(=20バイト)
のデータエリア
プログラム本体そのものが
入っているエリア
未使用
「10」ワード分のデー
タエリアを確保
.1 ロングワード(4バイト)
.w ワード(2バイト)
.b バイト(1バイト)
※ .dc.w 10
1ワードの確保.
初期値を10にセット
※ .ds.w 10
10ワードの確保
(初期値は不定)
「10」ワード分のデー
タエリアを確保
D0 をクリア (0x0000 → D0 の下2バイト)
ラベル a のメモリアドレスを A0 にセット
(0x00000020 → A0)
D0 と 9 の比較
比較結果による分岐
繰り返し実行
ラベル a のメモリアドレスを A0 にセット
(0x00000020 → A0)
A0がポイントしている
メモリアドレスに,D0 の中身を
書き込む
D0 + 1 → D0 (下2バイト)
0x0000, 0x0001, 0x0002,
..., 0x0009
A0 + 1 → A0
0x00000020, 0x00000022,
..., 0x00000032
オペランドの#の意味
• プログラム命令では
– #付き : 値を表す
move.w #0x1000, %d0
→ メモリの読み書きを行わない
– #無し : メモリアドレスなどを表す
move.w ADDR, %d0
→ メモリの読み書きを行う
• 擬似命令では
– ふつう # はない.例えば
.equ ADDR 0xffff00
.org 0x0400
.dc.w 0x4848
a: .ds.w 1
記法 (%a0)
move.w %d0, (%a0)
D0 の中身を,A0がポイントしている
メモリアドレスに書き込む
A0 の値が 0x00000020 ならば
0x20, 0x21 番地に,D0 の下2バイトを書き込む
メモリへの書き込み
move.l %d0, %a0
D0 の中身を A0 の中にコピー
メモリの読み書き無し
lea 命令と move 命令
lea s, %a0
ラベル s が示すメモリアドレスの値を A0 に格納
0x00000020 → A0
メモリアクセス無し
move.l s, %a0
ラベル s が示すメモリの中身を A0 に格納
<0x00000020 の中身 4バイト分> → A0
メモリからの読み出し
例題5.文字列の長さ
• 文字列の長さを数えるプログラム
今回の文字列データ: My Name is David!
• 文字列の先頭から1文字ずつ読み
– 0 で無ければ,「データレジスタD0 に1を足す」こと
を繰り返す
– 0 ならば処理を終える
実行後
文字列のデータ
(1文字で1バイト)
プログラム本体そのものが
入っているエリア
未使用
文字列の末端を
示す 0
ASCIIコード
• パソコン,ワークステーションで英数文字
データを扱うときの標準
ASCIIコード表
0 1 2 3 4 5 6 7
0
NULL DEL SP
0 @
P p
1
SOH DC1
! 1
A Q a q
2
STX DC2
“ 2
B R b r
3
ETX DC3
# 3
C S c s
4
EOT DC4
$ 4
D T d t
5
ENQ NAK
% 5
E U e u
6
ACK SYN
& 6
F V f v
7
BEL ETB
’ 7
G W g w
8 (BS)
CAN
( 8
H X h x
9 (HT)
EM
) 9
I Y i y
A
(LF)
SUB
* :
J Z j z
B
(VT)
ESC
+ ;
K
[
k {
C
(FF) (FS) , <
L
¥
l |
D
(CR) (GS) - =
M
]
m }
E SO
(RS) . >
N
^
n ~
F SI
(US) / ?
O
_
o DEL
青は特別用途
の1バイトデータ
緑は英数文字
データ
文字列
• My Name is David! のように,英数文
字が並んだもの
• 各1文字は1バイト
• 末尾の「0x00」 (これで1バイト)
文字列の終わりを意味する (文字列の長
さは変化するので,終わりを示すための記
号が必要」
文字列データのデータ
エリアを確保
アセンブラプログラム中での
文字列の書き方
.ascii "<文字列> 0"
ラベル str1 のメモリアドレスを A0 にセット
(0x00000020 → A0)
D0 をクリア (0x00000000 → D0)
0 との比較
(文字列の末端か?)
繰り返し実行
A0 + 1 → A0
0x00000020, 0x00000021,
..., 0x00000031
D0 + 1 → D0
0x00000000, 0x00000001,
..., 0x00000011
• 条件分岐、繰り返しには,分岐命令が登場
する
• 分岐命令では,プログラムカウンタの強制
的な書き換えが起こる
• 比較命令などで,コンディションコード
レジスタ(ステータスレジスタの下位1
バイト)が変化.分岐命令で利用され
る
おわりに