
2026/08/17 5:41
私はAm29000向けCコンパイラとウェブブラウザを開発しました
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
1998 年末から 1999 年 4 月にかけて、20 歳の著者オスカー・トーレド・G(Oscar Toledo G)は、自作コンピュータ(G11V1/G11V2)上で Am29000 プロセッサ向けの完全なオペレーティングシステム(「Windows Fénix」)、C コンパイラ、アセンブラ、テキストエディタ、およびウェブブラウザ(「BiYUBI」)を開発しました。このプロジェクトは、ハードウェアの極限(RAM 512 KB、CPU 12 MHz)ゆえにフラップディスクと EPROM 記憶を駆使して約 2 ヶ月で完了しましたが、メモリリークや乗算エミュレーションの不備といった重大な課題に直面しました。プロジェクトは当初、トランスピュータアーキテクチャ向けツールである DJGPP を使用してブートストラップされ、ブラウザのために RAM を確保するためスタック全体が EPROM から実行されました。システムでは、低速のプロセッサ上で高速なフォントレンダリングを実現するためにハードコーディングされたホームページキャッシュを採用しており、JPEG 対応についてはハードウェア制約により遅れが生じていました。1999 年末時点で著者はコードを約 5 万行に達し、その後には JavaScript 対応やリンカーの追加などの拡張が加えられました。現在、かつてモデムを通じて Prodigy を介してインターネットに接続したこのユニークなレガシースタックは、GitHub 上で保存され、エミュレーションされています。
Text to translate:
Between late 1998 and April 1999, 20-year-old author Oscar Toledo G. developed a complete operating system ("Windows Fénix"), C compiler, assembler, text editor, and web browser ("BiYUBI") for the Am29000 processor on his homebrew computers (G11V1/G11V2). The project, completed in roughly two months using floppy disks and EPROM storage due to extreme hardware limits (512 KB RAM, 12 MHz CPU), involved overcoming significant hurdles like memory leaks and missing multiplication emulation. Originally bootstrapped with tools like DJGPP for a transputer architecture, the stack ran from EPROM to preserve RAM for the browser. The system utilized a hardcoded homepage cache for fast font rendering on the slow processor, with JPEG support lagging due to hardware limitations. By late 1999, the author had written nearly 50,000 lines of code, and later enhancements included JavaScript support and a linker. Today, this unique legacy stack, which originally connected to the internet via Prodigy on a modem, is preserved and emulated online via GitHub.
本文
オスカル・トーレド氏による:Am29000 向け C コンパイラと Web ブラウザ開発の軌跡(1997-1999)
オスカル・トーレド ゴンザレス氏 2026 年 8 月 16 日更新
以前の記事でお伝えした通り、筆者は Am29000 プロセッサベースの自作パソコン(ホームブロー)向けに、32 ビットマシンコードによるウィンドウ化オペレーティングシステムを開発しました。 今回の記事では、そのプロジェクトにおいてC コンパイラとWeb ブラウザの開発過程について詳しくご紹介します。
1. プロジェクトの背景(1998-1999 年)
このプロジェクトは 1998 年のクリスマスイヤーから 1999 年の誕生日までに実行されました。 当時は 20 歳の筆者にとって、インターネットがメキシコで爆発的に普及する激動の時代でした。
その時代の状況
- キャリアの可能性: グラフィックデザイナーなどクリエイターにとって金運の年。
- デジタル・アポカリプスの恐怖: 人々は 2000 年のバグ問題(Y2K)を恐れ、『ザ・シンプソンズ』や映画『エクスキュード・オブ・デイズ』といった文化的現象が起きました。
機材と環境の変化
- ファクシミリからメールへ: 1997 年頃には HP DeskJet やモデムによる FAX が主流でしたが、翌年にはメールに代わられました。
- インターネット・カフェ(サイバカフェ): メキシコでの通称「サイバカフェ」の常連客として活動していました。
- Bazar Pericoapa などの店舗でコーヒーを飲みながらネット利用をしていましたが、コーヒーこぼれ問題が浮き彫りになりました。
- ハードウェアの制約:
- トランスピュータ(自作 PC)の RAM は 512 KB から増設されました(G11V2 で 512 KB→ROM に OS を入れ、RAM を解放)。
- CPU: Am29000(シングルバス構成でレジスタ管理が困難なアーキテクチャ)。
2. C コンパイラ開発の過程
Am29000 の複雑なアーキテクチャに合わせて C コードジェネレータを開発する必要がありました。
初期の試みと挫折
- High-C 29k / GCC: High-C は購入不可、GCC(バージョン 2.8.1)は最低でも 2 MB の RAM を要求しましたが、所持していたのは 512 KB でした。
- 移植の難しさ: アセンブラとリンカ以外での OS サポート不足もあり、コンパイラ自体をブートストラップするのは困難でした。
- Small-C コンパイラ: 1997 年 12 月の移植は失敗に終わりました(日記にも残っていない)。
DJGPP を活用した開発
- DJGPP (DJ G++): 80486 PC で動作する MS-DOS 向け GCC です。このコンパイラを元にしてトランスピュータ用を開発しました。
- 非標準の入出力関数を標準ライブラリに変換する必要があります。
コード進化:配列から構造体へ
開発日記に残されたフロッピーディスクには、ソースコード管理(SCCS)やバージョンごとの進化が記録されています。
ステップ 1: 木構造表現(配列使用)
初期のコードジェネレータでは、式木を表すための左子・右子・ノード値などの配列を使用していました。
- 制限: 配列は固定サイズのため、複雑な式には対応できませんでした。
// コード抜粋:cc0 ディレクトリ(初期版) ++ultimo_nodo; if(ultimo_nodo == TAM_ARBOL) { error("Expresión muy compleja"); // 非常に複雑な式 cancela(); } nodo_izq[ultimo_nodo] = izq; nodo_der[ultimo_nodo] = der; oper[ultimo_nodo] = op; esp[ultimo_nodo] = val; regs[ultimo_nodo] = 0; regsf[ultimo_nodo] = 0;
ステップ 2: 動的メモリ管理への移行(cc1 ディレクトリ)
休憩中に『トム・ラプラー』をプレイしていた時期に、設計を見直しました。動的メモリ割り当てを採用し、コードの可読性と汎用性を向上させました。
// コード抜粋:cc1 ディレクトリ(改良版) ultimo_nodo = malloc(sizeof(struct nodo)); if (ultimo_nodo == NULL) { error("Expresión muy compleja"); // 非常に複雑な式 cancela(); } /* ... */ ultimo_nodo->izq = izq; ultimo_nodo->der = der; ultimo_nodo->oper = op; // ...
アーキテクチャの違い:スタック vs レジスタ制御
Am29000 は多数のメモリー・レジスタを持ち、コンパイラ側で割り当てを管理する必要があるため、単純なスタックアーキテクチャとは異なります。
関数のプロローグ(開始コード)
仮想的な変数をローカルレジスタやメモリーに割り当て、引数をコピーし、スタックフレームを作成します。
/* ** 関数のプロローグ: ** o 仮想的な変数をレジスタまたはメモリーに割り当てる ** o 必要なスペースを割り当てる ** o 入力の引数をコピーする(必要な場合) */ prologo_funcion() { int variable, temp, por_copiar = 0, posicion, registro; /* --- レジスタ割り当てループ --- */ variable = 0; while (variable < variables_virtuales) { switch (virtuales[variable] & 3) { case 0: // メモリーに保持する必要がある変数か? if (virtuales[variable + 1] != 0) { // ポインタ処理 virtuales[variable] = (pila << 2) | 1; pila += virtuales[variable + 2] ? 8 : 4; } else { // ローカルレジスタに保持 if (virtuales[variable + 2]) pila_regs = (pila_regs + 1) & ~1; virtuales[variable] = pila_regs << 2; pila_regs += virtuales[variable + 2] ? 2 : 1; } break; case 1: // メモリーに保持すべき変数 // ... break; // ... } variable += 3; } /* --- スペース確保と引数コピー --- */ pila += por_copiar; // ... }
関数のエピログ(終了コード)
呼び出し元への戻り処理を簡素化しています。
epilogo_funcion() { if (buffer_vacio) return; if (pila_regs != 0) { // レジスタスタックの復元 gen_inst1("add", SI, 1, 1, pila_regs << 2); emite_linea("jmpi lr0"); emite_linea("asleu 65,lr1,gr127"); } else { // ... } vacia_buffer(); }
移植とデバッグの成果
- 開発期間: 全体で 2 ヶ月以上。
- 達成事項:
- PC 版と同じアセンブラリストを作成(1998 年 5 月 27 日)。
- C コンパイラをコンパイルし、アセンブルして正確なバイナリ生成を実現(1998 年 6 月 1 日)。
- メモリ・リークの解決: 式木メモリーの解放忘れによるバグを修正。
- 開発環境の完成: 32-bit C コンパイラ、アセンブラ、マシンコードテキストエディタ(50 KB)という完全なツールセットを構築しました。
注意: マシンコードのアセンブラ源ファイルは失われており、C で再実装した後に手動で移植して作成したようです。
3. ウィンドウ化された OS の実装(Fénix)
OS は ROM 上に格納され、起動時により多くの RAM を解放するように設計されました。
ハードウェア環境の移行
- G11V1 (ビッグエンディアン): 1998 年 6 月 18 日から G11V2 に移植。
- G11V2 (リトルエンディアン):
- RAM 512 KB の起動。
- OS を 1 MB の ROM へ移動させ、プログラムのための 256 KB を確保。
- ISA スロットと PCI スロットを併用。
バイナリ画像の調査
- FENIX.BIN: ROM 内のバイナリ画像を探し、著作権日付(1996-1999 / 1996-2000)を確認しました。
- エミュレータへの読み込み:
- PCI ビデオカードの初期化コードをパッチ適用(SCSI コントローラー SIM53C810 のシミュレーションなど)。
ベースのビデオカードドライバ実装。GD-5429
80 MB ハードドライブの再現
- イメージ作成:
を使用して 40 MB の FAT ファイルシステムイメージを作成しました。buildboot.c - 修正点:
- バイトオーダー(ビッグエンディアン→リトルエンディアン)の対応。
- ファイル名の文字コード変換(UTF-8→ローカル形式)。
- ディレクトリ構造と FAT エントリのアドレス配置の修正。
// buildboot.c の一部(イメージ作成ロジック) #define ALU(v1, v2, vc) \ if ((special[2] & 0x0400) == 0) { \ uint64_t tmp = v1 + v2 + vc; \ // ... overflow 処理 ... }
4. Web ブラウザ「Biyubi」の開発
プロジェクトの転換点
- 背景: Netscape Navigator を多用していたが、自宅にはインターネット接続がなく、開発の優先度は低かった。
- 決意: 1999 年 3 月 22 日、父の説得によりインターネット契約を獲得。Z280 コードをベースに HTML ブラウザの開発を開始。
機能の実装
- TCP/IP スタック: PPP (LCP, PAP) および AT コマンドによるモデム制御を実装。
- 初期動作: 1999 年 4 月 9 日、ローカル環境で動作する HTML ブラウザを完成。
- 接続テスト: 1999 年 6 月 24 日、モデム経由で Prodigy に成功接続し、ファイルダウンロードに成功しました(当時流行の Bitter Sweet Symphony がラジオから流れていた)。
バグ修正と最適化
- メモリ不足問題: 512 KB の RAM で動作するため、バイナリサイズを 362 KB と圧縮。
- ROM に Web ブラウザを焼き込み、プログラム用スペースを解放(G11V2 特有の構成)。
- データ領域の再配置:
- ブラウザ開始アドレス:
→0x80006980
の修正。0x80006d80 - ビットマップフォントキャッシュ(
)の追加による表示速度向上。Cache de tipos
- ブラウザ開始アドレス:
DNS と TCP/IP の実装(2026 年時点での再現コード)
現代の Internet Explorer や Netscape に対応させるため、DNS 解決と TCP コネクタを実装しました。
case 0x15: // DNS 解決 (resolver) pc0 = REG_B; c = regs[REG_AA(0x82)]; // ホスト名を取得 { struct addrinfo hints, *result; char hostname[256]; // ... 名前をバッファにコピー ... memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; // IPv4 hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(hostname, NULL, &hints, &result) == 0) { // IP アドレスをレジスタに格納 struct sockaddr_in *ipv4 = ...; regs[96] = ipv4->sin_addr.s_addr; } else { regs[96] = -1; // エラー } } break; case 0x1b: // TCP ソケット開放 (tcp_abrir) { struct sockaddr_in sserver; int s = socket(AF_INET, SOCK_STREAM, 0); if (s >= 0) { sserver.sin_family = AF_INET; sserver.sin_addr.s_addr = d; // 宛先 IP sserver.sin_port = htons(e); // 宛先ポート // connect() で接続確立 regs[96] = s; // ソケットファイルディスクリプタ } else { regs[96] = -1; // エラー } } break;
5. 今日:2026 年の試運転
Am29000 エミュレータ(GitHub)上で、ハードディスクイメージをロードし、**「Sistema Fénix」**を起動しました。
画面構成
- ウィンドウ化 UI: 左上に日付表示(クリックで変更可能)。
- アイコン: ボリューム(不可)、計算機、システムステータス、解像度変更(不可)。
- 固定メニュー: 右上のボタンからアクセス可能。
動作確認プログラム
以下のアプリケーションが正常に動作を確認しました:
- Ajedrez (チェス)
- Archivero (ファイル管理)
- Fénix C (開発環境)
- Circuito Impreso (PCB デザインツール)
- Publivisión (デスクトップ出版)
- Bloques (ゲーム)
プリンタ出力機能
- HP LaserJet IIP などに対応(PCL コマンド変換)。
の作成が必要。printer.txt
Web ブラウザ「BiYubi」の起動
- ファイルブラウザ(Archivero)を起動。
- 「Explorador de Internet」を選択。
- 注意: JPEG ライブラリは非対応のため、画像表示が遅くなります。これは Am29050 プロセッサへの移行前の時代的な制約です。
6. ポストモルトム(追想)と支援について
開発の思い出
- 集中力: 1 年で約50,000 行のソースコードを書きました。
- 進化: 2000 年頃にはリンカー付きコンパイラへ移行し、1 万行のソースをコンパイルする手間が減りました。JavaScript 対応や CSS の実装など、当時の最先端を追いました。
- インタビュー: Radioactivo 98.5 など、当時は非常に有名なメディアでも取り上げられました。
現在の状況
現在はフリーランス開発者として活動中です。Am29000 から Am29050、さらに最新のアーキテクチャへ進化を続けています。
記事の支援について
この記事の執筆やプロジェクト維持には多大な時間とコストがかかっています。もしよろしければ以下の方法でサポートいただけると幸いです。
- Ko-Fi: 月々 9 ドルのご寄付(映画代に充てることもできます)。
- nanochess への支援: ゴッドカルマが得られます。
- 書籍購入: Lulu.com での本やデジタルストアでの電子書籍・ゲーム購入もご支援の一環となります。
関連リンク
- Am29000 エミュレータ: https://github.com/nanochess/Am29000
- Am29000 向けウィンドウ化 OS の開発記事
- ブラウザ内動作のエミュレータ: 現在 G11V1 対応のみ
最終更新: 2026 年 8 月 16 日