エピ8 プログラムをRUNしましょう
***
エピ8 プログラムをRUNしましょう
***
初期化処理からメインループへと解読が進みました。
今ならプログラムを入力して、直接実行命令文でプログラムを実行したりできるはずです。
そうです。プログラムをRUNしましょう。プログラムが動作する全体像を把握します。
***
まず、プログラムを入力します。
プログラムは文番号を付けた命令文であればよくて、何でもよいのですが、ここは簡単そうな "END" にします。
10 END
すると、4806h 以降のメモリに記憶されます。
4806: 0C 48 0A 00 8F 0D
480C: 00 00 ...
4806h 番地の 480Ch は次文への番地で、続く 000Ah = 10 が文番号、8Fh が "END" の中間コードです。ODh は終端。
*
"RUN" したらいきなり "END" って、ヒドイよね(笑)。
*
準備ができたので、"RUN" を入力します。
直接実行命令文はエピ7で解読しました。メインループから 19CBh 番地に行って、中間コードから分岐先の番地を求めて、RET 命令でジャンプします。
"RUN" の場合は、中間コードは 83h で分岐先は 1CA5h 番地です。
1CA5: _1973h() # [4577h] = 00h; "RESTORE" 命令と同じ
1CA8: A = 00h
1CA9: [457Ah] = A # ファイル関係の状態(?)を 00h に設定
1CAC: [4565h] = A # プログラムの実行状態を 00h に設定
1CAF: _165Ah() # [HL] が 3Ah 以上か判定
1CB2: jr(NC,1CC2h)
"RUN" の後ろに数字が続くなら "GOTO" と同じ処理(1CB4h〜1CBFh)をしますが、無い場合は 1CC2h 番地に行きます。
1CC2: _184Ah() # ワークエリアの初期化
1CC5: _186Fh() # ワークエリアの初期化
1CC8: HL = 4806h # プログラムの先頭番地
1CCB: jr _1CBFh
1CBF: jp _19B9h
ワークエリアを初期化して、HL をプログラムの先頭にセットします。"RUN" と "GOTO" の違いは、このワークエリア等の初期化の有無ですね。
いずれにしても 19B9h へとジャンプします。1CBFh 番地を経由しているのは、こうするとコードサイズが1バイト削れるからです。
19B9h 番地では、次文への番地・文番号・命令文への番地を処置します。HL はプログラムの先頭 4806h を指していて、プログラムは 480Ch, 000Ah, 8Fh, 0Dh でしたね。
19B9: DE = 47FDh
19BC: BC = 0004h
19BF: LDIR # 番地と文番号を 47FDh〜4800h に転送
19C1: [4801h] = HL # 命令文の番地を 4801h,4802h に転送
LDIR とは、HL 番地から DE 番地に BC バイトを転送する便利な命令です。転送が終了すると HL と DE は BC だけ増加して、BC はゼロになります。
これによって、
番地(47FDh,47FEh) = 480Ch
文番号(47FFh,4800h) = 000Ah
命令文(4801h,4802h) = 480Ah
となります。
次は、47FDh,47FEh 番地を調べてプログラム(命令文)があるかを確認します。0000h だったら命令文がないことを意味するので 1B13h("END")に行きます。プログラムは 4806h 以降にあるので 47FEh で判定すれば十分ですね。
19C4: A = [47FEh] # = 48h
19C8: if A==00h: jp _1B13h
ここでは 47FEh 番地は 48h なのでジャンプせずに次に進みます。
続いて中間コードの分岐処理(19CBh 〜)です。が、直接実行命令文の場合と同じなので省略しますね。中間コード 8Fh の場合は 1B13h にジャンプします
"END" 命令を実行します。
1B13: _13BFh() # [4565h] = 01h
1B16: [4801h] = HL # HL = 480Bh
1B19: jp _124Dh
13BFh のルーチンをコールしてプログラムの実行状態 4565h を 01h に設定、命令文への番地4801h の値を更新して 480Bh にします。4801h を更新するのは "CONT" 命令で再開できるようにするためですね。
そして、メインループの先頭(124Dh)に行きます。
これが "END" 命令です。
*
1B16h 番地のコードで 4801h 番地に転送した HL(=480Bh)は、このプログラムの場合は文の最後を指していて、480Bh 番地の値は 0Dh です。
今回は END なので終了する(124Dh に行く)のですけど、END ではない命令文の場合は、...例えば "REM" などの場合は終端(0Dh)に着いたら 19A4h 番地に飛びます。
19A4: if [HL]!=0Dh:
19A8: _169Ah(3Ah) # 3A = ":"
19AC: [4801h] = HL
19AF: jr 19CBh
19B1: HL = [47FDh]
19B6: if [HL] == 0000h: jp 124Dh # main-loop
19B9: ...
19A4h のルーチンでは、終端に来ているかと、次文の番地 [47FDh] を確認します。次文の番地が 0000h なら終了でメインループに行きます。ここでさりげなく HL が更新されてますね。
それから...、19B9h のルーチンで番地・文番号・命令文を更新して、番地を確認して命令文があれば分岐処理をして命令文を実行します。
*
*
*
ここまでの流れを整理するとこんな感じになります。
* メインループにて、直接実行命令文 "RUN" を実行(HL=4459h)
↓
* 19CBh: 中間コードによる分岐(RUN:83h なら 1CA5h にジャンプ)
↓
* 1CA5h: "RUN" 命令を実行(HL=4806h, 19B9h にジャンプ)
↓
┏→* 19B9h: 番地・文番号・命令文を設定(19C4h に続く)
┃ ↓
┃ * 19C4h: 番地を確認(0000h なら終了、それ以外は 19CBh に続く)
┃ ↓
┃ * 19CBh: 中間コードによる分岐
┃ ↓
┃ * nnnnh: 命令文を実行(...、19A4h にジャンプ)
┃ ↓
┗━* 19A4h: プログラム続行かを判定(続行なら 19B9h に続く)
*
"END" 命令を実行するかプログラムの最後になるまでプログラムの実行は続きます。
*
あ、それから。終端の 0Dh だったら次の文に進むのですけど、文によってはマルチステートメントで続きがあることがあります。
10 A=1:B=2
のような場合なら、":" の続きを実行します。
***
**
*
プログラムを "RUN" しました。
ここまで長かったのですが "RUN" 自体は簡単でした。文番号の処置をすれば、あとは直接実行命令文と同じですから。
他に "CONT" や "NEW"、"CLR" も解読できています("BYE" もね)。
"LIST" は画面が必要なのでハードルが高いかもです。とすると、次は "LOAD" かな。
プログラムを LOAD できると夢が広がる気がする。
***
**
*
直接実行(が可能な)命令文とは、中間コードが 80h 〜 A8h である命令です。
具体的には、
SAVE, LOAD, VERIFY, LIST, RUN, CONT, NEW, CLR, BYE
などの、ほぼ直接実行でしか使わない命令と、
FOR, NEXT, IF, STOP, END, GOTO, GOSUB, RETURN, ON,
DEF FN, REM, LET, DIM, PRINT, INPUT, GET, CURSOR,
SET, RESET, MUSIC, TEMPO, WOPEN, ROPEN, CLOSE,
DATA, READ, RESTORE, POKE, INP#, OUT#, LIMIT, USR(,
ですね。
...、"RETURN" 命令も直接実行できるんだ。GOSUB した後に BREAK なり STOP した状態で、メインループにて "RETURN" を入力してみたらできた。
"STOP" 命令や "END" 命令は、直接実行命令文として実行できても、...ですけど、実行はできる。逆に、"NEW" 命令をプログラムとして実行すると、
10 NEW
として RUN したら自分が消えるよ。
実行できるか否かと、できて意味あるかは別ってことですね。
***
間違いの指摘とか疑問とか、ご意見・ご感想とかありましたら、どうぞ感想欄に!
***
2026.2.7 推敲
2026.2.11 加筆と推敲
2026.2.19 微推敲
2026.2.20 推敲
2026.2.24 微推敲
2026.3.18 微推敲




