Efficient Basic Coding for the ZX Spectrum (2020)

2025/12/14 21:04

Efficient Basic Coding for the ZX Spectrum (2020)

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

ZX SpectrumのROM BASICは、各プログラム行を「行番号 2 バイト」「長さ 2 バイト」「終端 0x0D」の順で格納します。1 行にはエラーが発生する前に最大127 のステートメントを含めることができます。通常、編集時は行番号を 1–9999 に限定していますが、POKE を使うと 0 や 9999 より大きい番号の行を作成できます。しかしこれにより問題が生じます(GO TO/RESTORE が 32767 超で失敗、GO SUB が 15871 超で失敗、LIST と編集が壊れる)。

インタプリタは行アドレス表を保持せず、GO TO・GO SUB・NEXT・FN 等のジャンプ命令に遭遇するたびにプログラム全体を先頭からスキャンします。これは前方の各行につき約 71 µs のコストがかかります。そのため、多くのジャンプや頻繁な呼び出しを含むコードを最初に配置すると、実行時間から数百ミリ秒を削減できます。

ZX‑Basicus は最適化を支援します。

  • --profile
    でどこに時間が使われているか表示します。
  • --mergelines
    が隣接する行を結合し、スキャン回数を減らします。
  • --delrem
    --delempty
    がコメントと空行を除去します。
  • --move
    はコードブロックを再配置し、参照先の番号(リテラルのみ)を更新します。

「GOTO‑with‑POKE」トリックは、システム変数 PROG (23635) と NEWPPC/NSPPC (23618/23620) を使ってインタプリタの検索開始点を設定し、NXTLIN (23637) も同様に利用できます。これらの手法により、ジャンプ時間が短縮され CPU 負荷が低減し、実際の Spectrum ハードウェア上で BASIC プログラムを高速化できるため、レトロゲーム愛好家や保存プロジェクトにも恩恵があります。

本文

「ZX Spectrum の BASIC 純粋プログラムの(非)効率」シリーズ第1回目

I. ライン番号について
II. 変数について
III. 式について
IV. 機能と時間計測
V. キャラクタベース画面操作


ZX Spectrum の ROM に組み込まれている Sinclair BASIC インタプリタは、多くの点でソフトウェアの傑作と言えるでしょう。特にアセンブリ言語で書かれた実装が優秀です。本シリーズでは、時間実行性能だけでなくメモリ使用量も最小限に抑えるために、BASIC で書くプログラムの重要ポイントをまとめます。

今回取り上げるのは 「ライン」 です。数値化する必要があることは昔からずっと変わりませんが、インタプリタ自体の効率も無視できません。まずは、このマシンにおけるプログラム行の制限を整理しましょう。

  • 番号と範囲

    • ライン番号は 2 バイト(ビッグエンディアン)で保存されます。0~65535 まで使えるようになっていますが、実際にはエディタでは 1〜9999 のみ許可されています。POKE で 0 や 9999 を超える番号を設定可能ですが、
      • GO TO
        /
        RESTORE
        は 32767 を超えると失敗します。
      • GO SUB
        が 15871 を超える行にジャンプすると呼び出しスタックが壊れます。
      • インタプリタは 65534 番を「編集バッファ実行中」を示すフラグとして使います。
      • 9999 を越える番号の行を
        LIST
        すると正しく表示されず、手動で編集すると 4 桁に切り詰められます。
  • 行長

    • 行長はライン番号の後に 2 バイト(リトルエンディアン)で格納され、番号や長さ自体は含まれません。
    • 最大 65 535 バイトまで許容し、最小 6 バイト(2 バイト番号 + 2 バイト長 + 1 バイト終端 + 1 空白)。
    • 実行時に 127 文以上を一行で書くと実行が中断されます(実際の上限)。

インタプリタの線形検索

BASIC は入力時に前処理され、キーワードはトークン化されますが、各行のメモリアドレス表は作られません。したがって「ある行を探す」操作は O(n) です。

  • GO TO
    /
    GO SUB
    /
    NEXT
    /
    FN
    は線形に検索し、追加行数毎に約 71 µs を消費します。
  • 行番号がプログラム先頭にあるほど実行速度は速くなります。

コードブロックを移動させるには ZX‑Basicus

--move
オプションで自動再番号付けと参照更新が可能です。


速化テクニック

  1. ループ・サブルーチンは先頭へ配置

    • RETURN
      は開始近くを指すようにし、同様に
      GO SUB
      も。
  2. パラメータ付きジャンプを避ける

    • 定数リテラル(例:
      GOTO 100
      GO SUB 2000
      )の方が速いです。
  3. 行長を最大化

    • 行は可能な限り長くし、127 文までを一行にまとめます。
      --mergelines
      で連続行を結合できます。
  4. コメント・データ削除

    • REM
      と空行は自動的に削除/末尾へ移動させるオプション
      --delrem
      --delempty
      を利用。
  5. 「GOTO + POKE」テクニック

    • システム変数
      PROG
      (23635、2 バイト)を先頭行アドレスに書き換えると、インタプリタはそれ以降の行だけを検索します。必要なら
      NXTLIN
      (23637)の値も POKE で変更可能です。

検索対象となる命令

命令コメント
GO TO
GO SUB
FNDEF FN 行を検索
RETURNスタックに保存された行へ戻る
NEXT対応する FOR へジャンプ
RESTORE
RUN
LIST
LLIST

要点まとめ

  • ループ・サブルーチン・ユーザー関数は先頭に配置。
  • 長い行はメモリ節約に貢献し、短い行は内部検索を遅くする。
  • インタプリタはアドレス表を持たず線形探索です(O(n))。
  • ZX‑Basicus の
    --profile
    --move
    --mergelines
    --delrem
    --delempty
    を活用。

目的 ― 実行箱全体のスコアを最大化 することです。

同じ日のほかのニュース

一覧に戻る →

2025/12/15 6:53

Anthropic Outage for Opus 4.5 and Sonnet 4/4.5 across all services

## Japanese Translation: アノマリーは複数のAnthropicサービスに影響を与え、特にSonnet 4.0、Sonnet 4.5、およびOpus 4.5モデルが対象でした。事件は2025年12月14日21:31(UTC)に初めて報告され、同日の21:46(UTC)に調査更新が行われました。この更新で問題は該当するモデルバージョンに起因することが確認されました。影響範囲は複数のAnthropicプラットフォームに及びます——claude.ai、platform.claude.com(旧console.anthropic.com)、Claude API(api.anthropic.com)およびClaude Codeです。タイムラインや次のステップについてはまだ発表されていません。

2025/12/15 6:05

2002: Last.fm and Audioscrobbler Herald the Social Web

## Japanese Translation: *変更は不要です。要約はすべての列挙された重要ポイントを正確に反映していますが、商業的実現可能性について小さな推測上の結論も追加されています。

2025/12/15 1:55

Hashcards: A plain-text spaced repetition system

## Japanese Translation: Hashcards は、すべてのフラッシュカードデータをプレーンマークダウンファイル(例:`Cards/Math.md` や `Chemistry.md`)として保持する軽量でローカル優先のスペースドリピテーションアプリです。ウェブ UI を起動すると (`hashcards drill <path>` が `localhost:8000` を開く)、レビュー履歴は SQLite データベースに保存されますが、カード自体は Git に対応し続けます。各カードはテキストのハッシュでコンテンツアドレス化されているためです。インターフェイスは作成をスムーズにすることを優先しており、クローズ削除は Mochi の冗長な `{{ }}` ではなく `[ ]` を使い、単一行ブロック(例:`Q: … A:` や `C: …`)でカードを定義します。 著者は Anki の煩雑な UI、“すべて期限切れを学習” ボタンの欠如、WYSIWYG エディティング、そして不安定なプラグインサポートを批判しています。Mochi は過度に冗長なクローズ構文、ノートタイプ自動化がないこと、および長期的には性能が劣る単純な倍率ベースのスケジューラーという欠点があります。Hashcards はこれらの痛みを解消し、最小限の摩擦、最適なスケジューリングのための高度な FSRS アルゴリズム、および任意のエディタや Unix ユーティリティ(例:`wc`、`awk`)でカードを編集できる機能を提供します。デッキは Git でバージョン管理・ブランチ化・マージが可能で、サードパーティサービスなしにユーザーがデータを完全にコントロールできます。 将来的には CSV ベースのカードインポート、Python で書かれたノートタイプロジック、および Git 主導の共有ワークフロー拡張をロードマップに含めています。これらの機能は協力を容易にし、コンテンツ生成を自動化するとともに、開発者が Hashcards を自身のプロジェクトへ拡張できるようにし、オープンソーススペースドリピテーション エコシステムを形成する可能性があります。