MSX Datapack wiki化計画

4章 BASICの内部構造

 BASICをより高度に利用するためには、BASICインタープリタの内部構造に関する知識が不可欠です。この章では、BASICの内部構造について説明します。

 4.1 ユーザーエリア

 ユーザーエリアの下限アドレスは、MSX1ではRAM容量が8K、16K、32K、64Kといろいろだったため異なっていましたが、MSX2の場合、RAM容量は最低でも64Kなので、ユーザーエリアの下限アドレスは常に8000H番地です。なお、これは【BOTTOM(0FC48H)】の内容から知ることができます。
 ユーザーエリアの上限アドレスは、ディスクが実装されていない場合、F380Hですが、ディスクが実装されている場合(Disk BASIC使用時)はドライブ数やディスク容量などにより変わります。これは電源投入後、CLEAR文を実行する前の【HIMEM(0FC4AH)】の内容から知ることができます。
 MSXを起動したと時のメモリ状態を図2.20に示します。


図2.20 BASICモードでのメモリの状態

 MSXのアプリケーションプログラムを作成する場合、必ずHIMEMの内容を確かめ、最悪の場合でも暴走しないように対処してください。対処の方法としては、次のようなものが考えられます。

  1. ワークエリアをリロケータブルにする
  2. ワークエリアをBOTTOMから確保する
  3. ドライブ数を減らすように指示して停止する

 MSXはディスクが実装されている場合も、[SHIFT]キーを押しながらリセットすることにより、ディスクを切り離すことができます。また、ディスクが1ドライブだけ実装されている機種を起動すると、2ドライブのシミュレータ機能が働き、2ドライブ分のワークエリアが確保されます。このような時は[CTRL]キーを押しながらリセットすると、2ドライブシミュレータを無効にして、起動することができます。これにより、1.5Kバイトのユーザーエリアを確保できます。

 4.2 ユーザーエリアの詳細

 BASIC使用時のユーザーエリアの状況を図2.21に、それらのエリアの開始番地へのポインタ情報を持つワークエリアを表2.15に示します。なお、このワークエリアは読み出し専用ですから、内容を書き換えた場合の動作に関しては保証されません。


図2.21 ユーザーエリアの状態

表2.15 各エリアの開始と終了アドレスを持つワークエリア

エリア名開始エリア終了アドレス
マシン語領域【HIMEM(0FC4AH)】ユーザーエリアの終わりまで
ファイルコントロールブロック【MEMSIZ(0F672H)】【HIMEM(0FC4AH)】-1
文字列領域【STKTOP(0F674H)】【MEMSIZ(0F672H)】-1
(文字列領域の空きエリアの先頭)【FRETOP(0F69BH)】
スタックエリア【SPレジスタ】【STKTOP(0F674H)】
フリーエリア【STREND(0F6C6H)】【SPレジスタ】-1
配列変数エリア【ARYTAB(0F6C4H)】【STREND(0F6C6H)】-1
単純変数エリア【VARTAB(0F6C2H)】【ARYTAB(0F6C4H)】-1
プログラムエリア【TXTTAB(0F676H)】【VARTAB(0F6C2H)】-1
ユーザーエリア【BOTTOM(0FC48H)】リセット時の【HIMEM(0FC4AH)】-1

 各ユーザーエリアの役割を以下に示します。

 ■BASICのプログラムエリア
 BASICで作成したプログラムは、ユーザーエリアの下限アドレス(MSX2では8000H番地)から収納され、その大きさはプログラム量ととともに変化します。

 ■変数領域
 変数領域はBASICプログラムエリアのすぐ後ろに位置し、プログラム実行時に使用された変数の名前や値の保存のために確保されます。この時の変数の格納形式を図2.22(単純変数の場合)、図2.23(配列変数の場合)に示します。なお、配列変数をDIM文で宣言せずに使用すると添字が10の配列としてエリアが確保されます。ただし、4次元以上の配列はかならず宣言する必要があります。


図2.22 単純変数の格納形式


図2.23 配列変数の格納形式

 ■フリーエリア
 プログラムエリアや変数領域が大きくなったり、スタックが多くなって、フリーエリアがなくなると「Out of memory」エラーになります。なお、BASICのFRE関数でPRINT FRE(0)を評価することにより、フリーエリアの大きさを知ることができます。

 ■スタックエリア
 BASICが使用するスタックエリアです。GOSUB命令やFOR命令などの実行時に上位アドレス側から順に使用されます。

 ■文字列領域
 文字列変数の内容を保存するために使用される領域で、上位アドレス側から順に使用されます。この領域の大きさはBASICのCLEAR文の第1パラメータで指定することができ、省略時は200バイトの大きさで確保されます。このエリアがすべて使われてしまうと「Out of string space」となります。BASICのFRE関数でPRINT FRE("")を評価することにより、文字列領域の残りの大きさを知ることができます。

 ■ファイルコントロールブロック
 ファイルの情報を保存する領域で、1ファイルごとに10BH(267)バイト分の領域が確保されます。ファイルいくつ分の領域を確保するかはBASICのMAXFILES文で指定でき、リセット時はファイル1つ分(MAXFILES=1)の領域が取られています。しかし、それとは別にSAVE、LOAD命令のために、常時かならず1つ分の領域が確保されているので、実際にはこれも含めて2つ分の領域が確保されていることになります。ファイルコントロールブロックの形式を表2.16に示します。

表2.16 ファイルコントロールブロック(FCB)の形式

変位ラベル意 味
+0FL.MODファイルがオープンされたモード
+1FL.FCABDOS用FCBへのポインタ(Low)
+2FL.LCABDOS用FCBへのポインタ(High)
+3FL.LSAバックアップキャラクタ
+4FL.DSKデバイスナンバー
+5FL.SLBインタープリタが内部で使用
+6FL.BPSFL.BUFの位置
+7FL.FLGいろいろな情報を持つフラグ
+8FL.OPS仮想的なヘッドの位置
+9〜FL.BUFファイルバッファ(256バイト)

 ■マシン語領域
  マシン語のプログラムを扱ったり、メモリを直接操作する場合の領域です。これらを行う場合はCLEAR命令によって、あらかじめ領域を確保しておく必要があります。

 ■ディスクのワークエリア
  ディスク実装時に確保されるワークエリアを図2.24に示します。この領域はディスクが実装されていない場合は存在しませんので注意してください。なお、図中左のラベルは、そこにこのアドレスの情報があることを意味します。


図2.24 ディスクのワークエリア

 4.3 BASICプログラムの格納形式

 BASICプログラムはメモリ上に図2.25のような形式で記憶されており、その内容には以下のような意味があります。


図2.25 テキスト格納形式

 ■リンクポインタ
  次の行へのテキストポインタが絶対アドレスで書かれています。

 ■行番号
  文字どおりプログラムの行番号が格納されており、通常は0〜65529(0000H〜FFF9H)の値が入ります。メモリを直接操作することにより65530以上の行番号を作ることも可能ですが、LISTコマンドはその行以降を表示しません。

 ■テキスト
  ここにプログラ本体が中間コード形式で格納されています。中間コードに変換されるものは、予約語(キーワード)、演算子、数値で、その他のもの(変数名や文字列定数など)はキャラクタコードの形で格納されます。中間コードを表2.17に、テキスト中の数値形式を図2.26に示します。
  キャラクタコードについては、巻末の付録を参照してください。なお、グラフィックキャラクタは「CHR$(1)+(グラフィックキャラクタコード+64)」の2バイト(2文字分)で格納されますので、グラフィック文字を取り扱う時には注意が必要です。

表2.17 中間コード一覧表

> EE CSNG FF9FGOTO 89 NAME D3 SGN FF84
= EF CSRLIN E8 HEX$ FF9BNEW 94 SIN FF89
< F0 CVD FFAAIF 8B NEXT 83 SOUND C4
+ F1 CVI FFA8INP FA NOT E0 SPACE$ FF99
- F2 CVS FFA9INKEY$EC OCT$ FF9ASPC ( DF
* F3 DATA 84 INP FF90OFF EB SPRITE C7
/ F4 DEF 97 INPUT 85 ON 95 SQR FF87
^ F5 DEFDBL AE INSTR E5 OPEN B0 STEP DC
\ FC DEFINT AC INT FF85OR F7 STICK FFA2
ABS FF86DEFSNG AD IPL D5 OUT 9C STOP 90
AND F6 DEFSTR AB KEY CC PAD FFA5STR$ FF93
ASC FF95DELETE A8 KILL D4 PAINT BF STRIG FFA3
ATN FF3EDIM 86 LEFT$ FF81PDL FFA4STRING$ E3
ATTR$ E9 DRAW BE LEN FF92PEEK FF97SWAP A4
AUTO A9 DSKF FFA6LET 88 PLAY C1 TAB ( BD
BASE C9 DSKI$ EA LFILESBB POINT ED TAN FF8D
BEEP C0 DSKO$ D1 LINE AF POKE 98 THEN DA
BIN$ FF9DELSE 3AA1LIST 93 POS FF91TIME CB
BLOAD CF END 81 LLIST 9E PRESET C3 TO D9
BSAVE D0 EOF FFABLOAD B5 PRINT 91 TROFF A3
CALL CA EQV F9 LOC FFACPSET C2 TRON A2
CDBL FFA0ERASE A5 LOCATED8 PUT B3 USING E4
CHR$ FF96ERL E1 LOF FFADREAD 87 USR DD
CNT FF9EERR E2 LOG FF8AREM 8F VAL FF94
CIRCLEBC ERROR A6 LPOS FF9CRENUM AA VARPTR E7
CLEAR 92 EXP FF8BLPRINT9D RESTORE 8C VDP C8
CLOAD 9B FIELD B1 LSET B8 RESUME A7 VPEEK FF98
CLOSE B4 FILES B7 MAX CD RETURN 8E VPOKE C6
CLS 9F FIX FFA1MERGE B6 RIGHT$ FF82WAIT 96
CMD D7 FN DE MID$ FF83RND FF88WIDTH A0
COLOR BD FOR 82 MKD$ FFB0RSET B9 XOR F8
CONT 99 FPOS FFA7MKI$ FFAERUN 8A ' 3A8FE6
COPY D6 FRE FF8FMKS$ FFAFSAVE BA
COS FF8CGET B2 MOD FB SCREEN C5
CSAVE 9A GOSUB 8D MOTOR CE SET D2


図2.26 テキスト中の数値形式

 数値は予約語や変数名との区別をつけるために「識別コード」と呼ばれる番号が割り付けられており、それを見ることで後に続く値がどのようなものかわかるようになっています。
 2バイトの数値の場合は、上位と下位バイトが逆に格納されます。符号付き数値については、識別コードの前に+または−の中間コードが置かれるのみであり、数値自体はかならず正の数で記憶されます。浮動小数点表記法についてはおおむね6.3のマスパック(Mathematical Package)の説明と同じですが、上記のように数値はかならず正の数で記憶される点に注意してください。2進数(&B)については、識別コードは割り当てられておらず、アスキーコードそのままの形で記憶されます。