【ITニュース解説】Cadenas de caracteres... en el BASIC del ZX Spectrum
2025年09月10日に「Dev.to」が公開したITニュース「Cadenas de caracteres... en el BASIC del ZX Spectrum」について初心者にもわかりやすく解説しています。
ITニュース概要
ZX Spectrum BASICの文字列は、当時メモリが許す限り長くできると思われていた。しかし、実際は他のBASICの255文字制限と異なり、約32KBの長さ制限があった。これはBASICインタプリタの内部構造に起因し、部分文字列を操作する機能も存在した。
ITニュース解説
記事の筆者は、子供の頃にSinclair ZX Spectrumというコンピュータでプログラミングを始めた経験から、Sinclair BASICという言語の文字列の扱いに独自の「普通」という感覚を持っていた。当時の筆者にとって、Sinclair BASICでできることは全て当たり前だった。
しかし、後年、学校でAmstrad PC-1512という別のコンピュータを使い、GW-BASICという別のBASIC言語を学んだ際、文字列の扱いに大きな制約があることを知って驚いた。GW-BASICでは、文字列の長さが最大で255文字に制限されていたのだ。これは、文字列のデータをメモリに格納する際、最初の1バイトにその文字列の長さを記録する効率的な方法が採用されていたためで、この1バイトの表現範囲が0から255までだったことによる。
ZX Spectrumを使っていた筆者にとって、この255文字という制限は信じられないものだった。なぜなら、ZX SpectrumのBASICでは、メモリが許す限りどんなに長い文字列でも扱えると感じていたからだ。実際に、ZX Spectrum 128kというモデルには、ROM(読み出し専用メモリ)にテキストエディタが組み込まれていた。このエディタで入力された文章は、ユーザーが指定した文字列変数にそのまま保存できた。たとえば、edit t$というコマンドを入力すると、エディタが起動し、そこで入力した内容がt$という文字列変数にすべて格納される仕組みだった。これはまるで、現代のプログラミング言語で、複数行にわたるテキスト全体を一つのデータ構造として扱うような、高度な機能が当時のBASICに標準で備わっていたかのようだった。
筆者は、この「メモリが許す限り文字列を長くできる」という感覚が本当に正しいのかを確かめるため、簡単なプログラムをZX Spectrum BASICで作成し、実験を試みた。そのプログラムは、a$という名前の文字列変数に、+という文字を繰り返し追加し続け、その都度a$の現在の長さを表示するというものだ。この実験は、文字列がメモリを使い果たし、最終的にシステムがメモリ不足のエラーを出すまで続けることを想定していた。ZX Spectrum BASICが利用できるRAM(ランダムアクセスメモリ)の空き領域は約38KB(キロバイト)なので、この範囲内で文字列がどれだけ大きくなるかを確認しようとした。
プログラムを実行し続けた結果、a$という文字列変数は13781文字まで格納できた。ZX Spectrum BASICでは、プログラムが中断されても変数の内容は保持されるため、プログラム停止後にprint len a$と入力することで、この長さを正確に確認できた。
しかし、13781文字という長さは、ZX Spectrum BASICが利用できる約38KBのメモリ全てを使い切っているわけではないように見えた。当時のコンピュータのメモリ状況を調べるためには、特殊な方法が必要だった。ZX Spectrum BASICには、現代のプログラミング言語のようにメモリを明示的に解放するfree()関数のようなコマンドは用意されていない。しかし、ROMに組み込まれたルーチンの中に、メモリの使用状況を計算する機能があった。具体的には、usr 7962というコマンドを実行することで、その時点での空きメモリ量を調べることができた。このルーチンを使って調べた結果、約27KBの空きメモリがあることが示された。
ここで、文字列a$が占めるメモリ(約13KB)と、この時点での空きメモリ(約27KB)を合計すると約40KBになる。これは、ZX Spectrumを起動した直後の初期の空きメモリ量(約40KB)とほぼ一致する。わずかな差(約157バイト)は、BASICインタプリタがプログラムや変数管理のために内部的に使用しているデータ構造によるものと考えられる。このことから、文字列の長さが13781文字で限界に達したのは、単に物理的なメモリが足りなくなったためではないことが明らかになった。
では、なぜ13781文字で限界に達したのだろうか。この中途半端な数字は、メモリの物理的な限界とは別の理由を示唆している。
ZX Spectrum BASICが文字列の長さをどのように管理しているかを調べるため、ROMの内部コードを解析する(逆アセンブルする)必要があった。len関数、つまり文字列の長さを返す関数がどのように実装されているかを調べると、それはSTK_FETCHというルーチンを使って、文字列のアドレスと長さを取得していることが判明した。ZX Spectrum BASICでは、数値は5バイトで、文字列は4バイトで管理されていた。この4バイトの内訳は、文字列がメモリ上のどこにあるかを示す「アドレス」に2バイト、そしてその文字列の「長さ」に2バイトが割り当てられていた。
この「長さ」を管理するのに2バイト(16ビット)が使われているという事実は重要だ。16ビットで表現できる最大の数値は65535だが、通常、文字列の長さの場合は符号なし整数として最大32767または32768までを上限とすることが多い。つまり、ZX Spectrum BASICの文字列の長さは、この2バイトのデータ構造によって最大32768文字までしか扱えないという制約があるのだ。 今回の実験で13781文字という結果が出たのは、この32768文字という理論上の上限に達する前に、他の変数やプログラム自体がメモリを消費し、その結果として、これ以上文字列を長くするための連続したメモリ領域が確保できなくなったためと推測できる。つまり、この文字列の長さの限界は、メモリの物理的な限界というよりも、BASICインタプリタの内部的な設計(文字列の長さを2バイトで管理するというデータ構造)によって課された「人工的な」制限だったのだ。
さらに、ZX Spectrum BASICには現代のプログラミング言語でよく見られる、非常に便利な文字列操作機能が備わっていたことにも驚かされる。それが「文字列スライス」だ。文字列スライスとは、文字列の一部を切り取ったり、置き換えたりする機能のことで、例えばPythonのような言語では日常的に使われる。
let a$ = "Eh hola ZX Spectrum"という文字列があったとして、let a$(1 to 4) = " M"と記述すると、a$の1文字目から4文字目までが指定した文字列" M"に置き換えられる。その結果、元の文字列は" Mola ZX Spectrum"と変化する。これは、プログラムの中で特定のテキストの一部だけを効率的に変更したい場合に非常に役立つ機能だ。
このように、古いコンピュータのBASIC言語にも、現代のプログラミングに通じる高度な文字列管理の仕組みや便利な機能がすでに存在していたことがわかる。当時の限られたリソースの中で、どのようにデータを効率的に扱っていたのか、そしてプログラミング言語の設計思想がどのように進化してきたのかを考える上で、非常に興味深い事例と言えるだろう。