エピ13.3 FOR ループがネストしたらどうなる
***
エピ13.3 FOR ループがネストしたらどうなる
***
FOR ループのネストの例です。九九の表を作ります。
10 FOR I=1 TO 9
20 FOR J=1 TO 9
30 PRINT I*J,
40 NEXT J
50 PRINT
60 NEXT I
BASICを始めたら誰でもやるよね。罫線を入れたり、桁を綺麗に揃えたり、...しているうちに徐々に文字列の扱いを覚えるのさ。
*
*
*
さて。ネストしている FOR 命令文の処理を観察しましょう。
1D7Dh 番地以降の処理ですが、少し前の 1D6Fh から見ますね。
*
ネストしていない場合は次のように実行ステップが進みました。
1D6F: HL = [4648h] # HL = 4787h FOR領域の使用中の番地
1D72: DE = [47F0h] # DE = 2049h = 'I',20h ループ変数名
1D76: A = [4803h] # A = 00h ネスト数1
1D79: inc A # A = 01h
_1D7A:
1D7A: dec A # A = 00h, Zf = 1
1D7B: jr Z, 1D9Ch # JR
:
:スキップ
:
_1D9Ch:
1D9C: HL = 4804h # HL = 4804h
1D9F: A = [HL] # A = 00h
ネスト数1を調べて0なので、1D7Bh 番地から 1D9Ch 番地にジャンプです。
*
ネスト数1が1の場合は次のようになります。
1D6F: HL = [4648h] # HL = 4774h FOR領域の使用中の番地
1D72: DE = [47F0h] # DE = 204Ah = 'J',20h ループ変数名
1D76: A = [4803h] # A = 01h ネスト数1
1D79: inc A # A = 02h
_1D7Ah:
1D7A: dec A # A = 01h; Zf = 0
1D7B: jr Z, 1D9Ch # ジャンプしない(2回目はジャンプ)
:
1D7D: ex AF,AF'
1D7E: A = [HL] # A = 49h = 'I' FOR領域の変数名の1文字目
1D7F: A -= E # A = FFh
1D80: B = A # B = FFh
1D81: inc HL # HL = 4775h
1D82: A = [HL] # A = 20h FOR領域の変数名の2文字目
1D83: A -= D # A = 00h
1D84: A |= B # A = FFh
1D85: BC = 0012h
1D88: HL += BC # HL = 4787h
1D89: jr Z, 1D8Eh # 変数名が不一致なのでジャンプしない
1D8B: ex AF,AF'
1D8C: jr 1D7Ah # ループ
_1D8Eh:
:
_1D9Ch:
1D9C: HL = 4804h
1D9F: A = [HL] # A = 01h
1D7Bh 番地では、ネスト数1が1なのでジャンプせず、1D7Dh 以降の処理に進みます。
1D7Dh 以降では、新しく始まる FOR ループのループ変数名(47F0h)とFOR領域に保存された既存の変数名(4648h)とを比較します。
新しい変数名は 'J' で、既存の変数名は 'I' なので一致せずです。
それで 1D8Ch 番地から 1D7Ah 番地にジャンプして、2回目の 1D7Bh 番地で 1D9Ch にジャンプです。
FOR ループがネストする際に、外側の FOR ループで使用しているループ変数と同じ変数名だったら不具合なのでエラーにするんですね。きっと。
*
*
*
...、と思っていたら違いました。次のプログラムの場合、
10 FOR J=1 TO 3 :PRINT J;
20 FOR J=11 TO 13 :PRINT J;
30 NEXT J
40 END
エラーにはならなくて、PRINT 文で、
1 11 12 13
と表示されます。文番号 10 の FOR 命令文が、文番号 20 で上書きされているかのような動き。
なんならね。次のようなプログラムだと、
10 FOR A=1 TO 3
20 FOR B=1 TO 4
30 FOR C=1 TO 5
40 FOR D=1 TO 6
50 FOR B=1 TO 7
60 PRINT A,B,C,D
70 NEXT
80 NEXT
エラーにならないし、文番号 20, 30, 40 の FOR 命令文が無かったかのような動きをするのです。
*
1D8Eh 番地からの処理を確認しましょう。
1D8E: [4648h] = HL # HL = 4787h FOR領域の使用中の番地を更新
1D91: ex AF,AF'
1D92: dec A # A = 00h
1D93: HL = 4803h
1D96: B = [HL] # B = 01h
1D97: [HL] = A # HL = 4803h; A = 00h ネスト数1を更新
1D98: A -= B # A = FFh
1D99: inc HL # HL = 4804h
1D9A: A += [HL] # A = 00h
1D9B: [HL] = A # HL = 4804h; A = 00h ネスト数2を更新
[4648h] を更新して 4787h にしています。ネスト数1とネスト数2は -1 して 00h にしています。つまり外側の FOR ループの情報を消して、ネストが無かったことに。
これで仕様通りなのか。何か意図があってのコードなのだろうけど。これで良いのか。謎すぎるよ。
***
ひとつの可能性としてですが。FOR ループを Break したいときに使うと言うのはどうでしょう?
10 FOR A=1 TO 9999999
20 :
90 NEXT A
のような FOR ループを始めてしまった後で、ループを止めたいときに、
10 FOR A=1 TO 9999999
20 :
30 IF ... THEN FOR A=1 TO 1:GOTO 90
40 :
90 NEXT A
とすれば、次の NEXT でループが終わる。最終値が不明でも使えて便利では。
*
もうひとつの可能性ですが。
10 S=0
20 FOR A=1 TO 3
30 FOR B=1 TO 4
40 FOR C=1 TO 5
50 S=A+B+C
60 IF ... GOTO 10
70 NEXT
80 NEXT
90 NEXT
文番号 60 から文番号 10 に戻った場合、FOR ループの状況によらずに最初からやり直しができる。
あるいは、...
10 S=0
20 GOSUB 100:PRINT S
30 :
40 GOSUB 100:PRINT S
50 :
60 END
100 FOR A=1 TO 100
110 S=S+A
110 IF ... THEN RETURN
120 NEXT
130 RETURN
GOSUB したルーチンで FOR ループがあってループ中にリターンする場合、FOR ループを Break する処理をせずにリターンしてもOKだ(次にこのルーチンを GOSUB してエラーにならない)
意外と利用できる状況があるのかな。...、でもバグを作りそうで利用したくないかも。BASICにはローカル変数など言う概念は無いからね。利用するなら自己責任で変数を管理してね。
***
そもそも。ネスト数を 4803h と 4804h の2つで管理しているのが謎。見た感じでは同様に増減しているけれど、全く同じなら2つある意味がない。どこかで差異があるのか。それはどこなのか?
手掛かりを求めてアマゾンの奥地に向かうべきか。
***
**
*
***
**
*
NEXT I の I は省略可能なのですけど、省略した方がよいのか考えてみました。
メモリが2バイト(少くとも1バイト)節約できるのは確かだけど。速度はどうだろう?
'NEXT' 命令のコードを見る限りでは、ループ変数名 I の有無で影響を受けるのは
1DCB: _2556h() ; 変数名チェック
1DD4: _1E41h() if NC ; DE = [HL] ループ変数名
の2つのルーチン。
2556h のルーチンは、ループ変数名が省略されていると、NEXT のすぐ次が ":" だったら7ステップ目でリターンです。変数名があると、...あれ長い、... NEXT I のように NEXT と I の間にスペースがあるとそれをスキップするだけで5ステップ、I をチェックして、...25 ステップ目でリターンします。
1E41h のルーチンはループ変数名があればコールはされないのでステップ数は0です。省略したらコールされて5ステップでリターンします。
省略しない場合: 0 + 25 = 25 ステップ
省略した場合 : 5 + 7 = 12 ステップ
これだけを比べると省略した方が良さそう。FOR と NEXT が自明に対応しているなら省略するものアリですね。
FOR と NEXT がケース文などでダイナミックに対応する場合は、
:
10 IF S>=0 THEN FOR I=1 TO 2
20 IF S =0 THEN FOR J=2 TO 4
30 IF S<=0 THEN FOR K=3 TO 6
40 ...
:
(何かの処理)
:
50 IF S=0 THEN GOTO 40
60 IF S<0 THEN NEXT K
70 IF S=1 THEN NEXT I
80 IF S>2 THEN NEXT J
ループ変数名が付いているとデバックが捗るかもだけど。どう思う?
***
**
*
...。そう言えば数式の処理は?
F = A + B * C + D * E
とかは、括弧がなければ3値で処理かな?
2251h ってとても面倒なのですけど。こちらを調べてみたら良さそうな?(明らかな逃避行)
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2026.3.22 エピタイ修正
2026.5.3 エピタイ修正




