5. 反復処理

条件分岐による反復処理を行うと,さまざまな計算が実現できます.

基本的な枠組み

以下の枠組みによって,指定された条件を満たすまで,反復処理を行います.
  1. 計算をする
  2. 条件を満たしているならば,プログラムを終了する
  3. (条件を満たしていないので)1に戻る

基本的な枠組み


反復処理の例 "1から10までの和"

反復処理を使ったプログラムの例として, "1から10までの和" を計算するプログラムを考えてみます.下図の左側が Little Man Computer CPUシミュレータ で実行できるプログラムです.このプログラムは教科書 図8.2 (下の図の右側)のプログラムを Little Man Computer CPUシミュレータ 用に書き直したものです.

LMCアドレスLMC命令アドレス命令意味高水準言語
0LDA 111001load 2001AC←2001
1ADD 121002add 2002AC←AC+2002
2STA 111003store 20012001←ACsum←sum+i
3LDA 121004load 2002AC←2002
4SUB 131005subtract 2003AC←AC-2003
5STA 121006store 20022002←ACi←i-1
6BRZ 81007jumpzero 1009条件分岐(ジャンプ)
7BRA 01008jump 1000無条件ジャンプwhile i ≠ 0
8LDA 111009load 2001AC←2001
9OUT1010write結果の出力write(sum)
10HLT1011haltプログラム停止
11DAT 020010変数sum←0
12DAT 10200210変数i←10
13DAT 120031変数1

各命令の対応関係は以下のようになっています.LMC(Little Man Computer)の命令セットについては,Little Man Computer CPUシミュレータの命令セットをみてください

LDA ADD STA SUB BRZ BRA HLT OUT
load add store subtract jumpzero jump halt write

プログラムの読み込みと実行

"1から10までの和"を実行するために左側のテキストフィールドに以下のプログラムをコピー & ペーストして,「Submit」ボタンを押します.

LDA 11
ADD 12
STA 11
LDA 12
SUB 13
STA 12
BRZ 08
BRA 00
LDA 11
OUT
HLT
DAT 00
DAT 10
DAT 01       

"RAM"と書かれた"メインメモリ" にプログラムが読み込まれたことを確認したら,"STEP" をクリックしてプログラムを実行し,反復処理の過程を追いかけてみましょう.実行速度は"OPTIONS"メニューの「default fast」, 「default normal」, 「default slow」の3つから選ぶことができます.

1. "LDA 11" の実行

LDA命令により,"メインメモリ" の11番地の値 "0" を "アキュムレータ" に読み込みます.

1. "LDA 11" の実行

2. "ADD 12" の実行

ADD命令により,"アキュムレータ" の値である "0" に "メインメモリ" の12番地の値 "10" を加えて,結果の値を "アキュムレータ" に格納します.

2. "ADD 12" の実行

3. "STA 11" の実行

STA命令により,"アキュムレータ" の値 "10" を "メインメモリ" の11番地に書き出します.

3. "STA 11" の実行

4. "LDA 12" の実行

LDA命令により,"メインメモリ" の12番地の値 "10" を "アキュムレータ" に読み込みます.

4. "LDA 12" の実行

5. "SUB 13" の実行

SUB命令により,"アキュムレータ" の値 "10" から "メインメモリ" の13番地の値 "1" を引き,結果の値を "アキュムレータ" に格納します.

5. "SUB 13" の実行

6. "STA 12" の実行

STA命令により,"アキュムレータ" の値 "9" を "メインメモリ" の12番地に書き出します.

3. "STA 12" の実行

"STA 12" なので "アキュムレータ" の値 "9" を12番地に書き込みます.

7. "BRZ 8" による条件分岐

BRZ命令により,"アキュムレータ" の値がゼロだった場合,"プログラムカウンタ" の値を8にして,プログラムの実行を8番地にジャンプします.

7. "BRZ 8" による条件分岐

最初の実行では "アキュムレータ" の値は "9" であり,ゼロではないのでジャンプせずに次の命令を実行します.しかし,実行が進むにしたがって,5の "SUB 13" により12番地の値が1つずつ小さくなり,ゼロになるときがきます.

8. "BRA 0" による無条件ジャンプ

BRA命令により,無条件で "プログラムカウンタ" の値を0にして,プログラムの実行を0番地にジャンプします.

8. "BRA 0" による無条件ジャンプ

9. 1〜6 の反復と実行の終了

7に書いたように"メインメモリ" の12番地の値が "0" になるまで,1〜6の実行を反復します."メインメモリ" の12番地の値が "0" になると,"BRZ 8" によりプログラムの実行は8番地にジャンプします.そこで "LDA 10"が実行された後,9番地の"OUT"が実行され,シミュレータのOUTPUTに"55"と表示されます.その後,10番地の"HLT" が実行されプログラムが終了します.

解説

このプログラムの実行によって,メインメモリ上の11〜13番地の値は,以下のようになることがわかります.

ラベルの利用

Little Man Computer CPUシミュレータでは,機械語をそのまま入力する(例 511)代わりに,人間に理解しやすいオペコード(例 「LDA」)を使って「LDA 11」のようアセンブリ言語を使ってプログラムを入力することができます.ただ,ここまで「11番地の値をロードする」,「0番地にジャンプする」のようなアドレス(番地)の情報は数値で与えていましたが,命令を追加したり減らしたりするたびに番地が変わるので,そのたびに変更をする必要がありました.この問題を解決するために,アセンブリ言語では「ラベル」と読ぶように,番地に名前をつけることができます.「ラベル」に使える名前はオペコード以外で,英数字および「_」ですが,数字だかからなるラベルは作ることができません.

ラベルを使うと,「1から10までの和」のプログラムは以下のように書くことができます.

LOOP    LDA SUM
        ADD i
        STA SUM
        LDA i
        SUB ONE
        STA i
        BRZ L
        BRA LOOP
L       LDA SUM
        OUT
        HLT
SUM     DAT 0
i       DAT 10
ONE     DAT 1
左側のテキストフィールドにプログラムをコピー & ペーストして,「Submit」ボタンを押します.得られる機械語プログラムは同一です.