APPLE-1BASICは4KBの整数型BASICインタプリタで、APPLE-1用のBASICインタプリタとして提供されていたものです。

APPLE-1 BASICは、当時一般的なプログラム配布メディアであったカセットテープで供給され、マニュアルによると読み込みに30秒程度かかったようです。

マシンにダウンロードしてから使用するという観点では、6502-CORE 似た手順を味わえるといえるかもしれません。

APPLE-1 BASICの機能や利用法の詳細は、下記のマニュアルをご参照ください。

ちなみに、APPLE-1 BASICはWozによって、APPLE-1のハードウェアが組み立てられる前に、ハンドアッセンブルで作成したとのことです。

伝説が生まれるような話題がそこここに転がっていますね。

APPLE-1 BASICの特徴

APPLE-1 BASICは整数型BASICということで、例えばPalo Alto TinyBasicをイメージするかもしれませんが、4K BASICと容量が大きくなっているため、機能が拡張されていて強力になっています。一方で、他の多くのBASICとの違いがあって戸惑ったりすることがあるので、使用する上での注意点をいくつかまとめてみました。

  • 入力されているプログラムを消去するのはNEWではなくSCRコマンド
  • プログラムの最後にEND文を記述しないと実行終了時にエラーになる
  • 多くのBASICでPRINT文で使うTAB関数の使用法が異なる(TAB()はPRINTと独立して使う文になっている)
  • 配列が使える
  • 文字列変数が使える
  • 四則演算に加えて余り(MOD)演算が行える
  • PEEK関数とPOKE文が利用できメモリの読み書きができる
  • CALL文で機械語に制御を移すことができる
  • 多くのBASICインタプリタでは、プログラムの実行時に文法エラーが検出されるのに対し、Apple 1 BASICでは、プログラムの入力時に文法エラーが検出される

APPLE-1 BASICのソースコード

APPLE-1 BASICのバイナリコードを解析してソースコードを再現して公開しているサイトはいくつかありましたが、多くのソースコードで、アドレスを含むテーブルなどが適切にアセンブリコードに復元できていないという問題(それぞれの方が復元されているコードは、不十分とはいってもとてつもなく労力を要するものです。解析し、成果を公開されていることに感謝します。)が見られました。

それらの中で、最も解析が進んでいると感じられた下記のソースコードを利用させていただき、APPLE-1 BASICを6502-CORE 用に移植してみました。

なお、移植したBASICインタプリタのワークエリアの上限を示すHIMEMはあらかじめ$BF00に拡張しています。

APPLE-1 BASICインタプリタの起動と実行

APPLE-1 BASICインタプリタは、以下の2種類の方法で起動することができます。

  • \item 1つ目は、\ref{sec:wozmon-boot}節で紹介した手順でまずWozMonを起動し、WozMonのプログラム起動機能を利用してAPPLE-1 BASICインタプリタを起動する方法
  • \item 2つ目は、\ref{sec:wozmon-boot}節で紹介したWozMonを起動する直前までの操作手順は同じですが、単にGコマンドを入力してWozMonを起動するのではなくGE000と入力して、Universal Monitor から直接APPLE-1 BASICインタプリタを起動する方法

APPLE-1 BASICインタプリタだけを使用したいのであれば、2番目の方法が迅速で便利です。

APPLE-1 BASICを起動したら、その特徴的な構文を含むプログラムを入力し実行してみましょう。

TAB文の使用例

APPLE-1 BASICはTABがPRINT文で使える関数ではなく、独立したTAB文になっています。

この機能を利用した簡単なプログラム例を「TAB文を使用したプログラムの入力例」に示します。

見慣れないTABの使い方なので少し戸惑いますね。

TAB文を使用したプログラムの入力例

入力したプログラムの実行例を「TAB文を使用したプログラムの実行例」に示します。

プログラムの最後にEND文を置かなかったので、エラーが発生しています。プログラムの最後にENDがないとエラーが発生するのAPPLE-1 BASICの特徴ですね。

60行にENDを置くとこのエラーは解消されます。

TAB文を使用したプログラムの実行例

配列の使用例

APPLE-1 BASICでは配列が使用できるので、エラトステネスのふるいを使用した素数を求めるプログラムSIEVE.BASを動かしてみましょう。

使用するプログラムを「配列を使用したエラトステネスのふるいの入力例」に示します。

プログラムは、あらかじめテキストエディタで作成しておき、TeraTermの[Send file…]の機能を使用する方法でBASICにロードするとよいでしょう。

配列を使用したエラトステネスのふるいの入力例

プログラムの実行例(途中)を「配列を使用したエラトステネスのふるいの実行例」に示します。

\ref{sec:c-sieve}節で示しているC言語で書かれたプログラムと比較すると、ふるいの実行にちょっと処理時間がかかります。

配列を使用したエラトステネスのふるいの実行例

APPLE-1 BASICでの実行時間は2MHzで53秒程度でした。実数型BASICのOSI BASICでの実行時間の73秒に比べると1.4倍近く高速なものの、やはりCコンパイラとは大きく水をあけられる結果となりました。

この例では、一つの配列で10000要素の配列を定義して使用しましたが、プログラムを書き込んでいない状態では、16000要素程度の配列を定義できました。

PEEK,POKE,CALLの使用例

PEEKでメモリの値を読み出し、POKEでメモリの内容を変更する実行例を「PEEK,POKE,CALLの実行例」に示します。また、POKEでメモリ中に機械語のプログラムを配置した場合には、CALL文でそのプログラムを呼び出すことが可能です。

なお、CALL文で Universal Monitor のウォームスタートやコールドスタートを呼び出して、BASICからモニタに復帰することができます。

Universal Monitor のエントリアドレスを以下に示します。

  • ウォームスタート:-125:$FF83
  • コールドスタート:-128:$FF80

CALL文を使用してUniversal Monitor コールドスタートを呼び出しモニタに復帰する例を「PEEK,POKE,CALLの実行例」に示します。

PEEK,POKE,CALLの実行例