世界を動かす技術を、日本語で。

Show HN: X86CSS – CSSで書かれたx86 CPUエミュレーター

概要

x86CSS は、 CSSのみ で動作するx86エミュレータ。 JavaScript不要 で、C言語のプログラムを8086マシンコードにコンパイルし、CSS上で実行。 HTMLも最小限 (styleタグのみ)で動作可能。 独自のビルド手順や カスタムI/O をサポート。 趣味・教育・アート目的の 非実用的だが革新的なプロジェクト

x86CSSとは

  • CSSだけ でx86 CPU(8086互換)をエミュレートするプロジェクト
  • JavaScriptを一切使用しない 設計
  • 上記デモは GCCでCから8086マシン語に変換したコード をCSS上で実行
  • GitHub でソースコード公開
  • Chromium系ブラウザ で動作(Firefoxでは一部制限あり)

よくある質問

  • CSSはプログラミング言語か?
    • このプロジェクトを見れば、その可能性を再考する機会
  • JavaScriptは本当に不要か?
    • 完全CSSのみで実行可能
    • clockの安定化・高速化目的でscriptタグを利用するが、無効化しても動作
    • アニメーションとstyle container queriesでクロック生成
    • ユーザーの操作不要でプログラムが実行
  • HTMLも不要か?
    • 実質CSSのみで完結
    • 読み込みにstyleタグは必要(HTML最小限)
    • FirefoxはHTMLなしでCSS読込可能だが、現状Chromium専用
  • プリプロセッサは?
    • 手書きCSS が基本
    • 繰り返し部分のみPythonスクリプトで自動生成
  • 実用性は?
    • 実用性は低いが、 アート・実験・教育 用途
    • パフォーマンス目的なら素直にCSSで書く方が良い
  • 自作プログラムは動かせる?
    • 8086アセンブリまたはCから自作プログラムを実行可能
    • ビルド手順は後述

x86アーキテクチャ対応状況

  • 主要な命令セット をサポート
  • 必要な命令だけを都度実装
  • 一部フラグ(CF/OF等)の未実装や挙動の違いあり
  • 16bit(8086)ベース、現代x86(64bit)とは異なる
  • 命令テーブル やサポート状況をドキュメント化

ビルド・実行方法

  • 8086アセンブリ または C言語 でプログラム作成
  • GCC-IA16 (16bit x86用GCC)を利用
  • build_c.py でC→アセンブリ→バイナリ生成
    • program.bin(バイナリ)、program.start(エントリーポイントアドレス)を作成
  • build_css.py でCSSエミュレータに組み込み
  • Linux/WSL1/2で動作確認済み(macOS未検証)
  • メモリサイズ はデフォルト0x600バイト(変更可能)
  • プログラムは アドレス0x100 からロード

カスタムI/Oインターフェース

  • 0x2000: writeChar1(1バイト出力)
  • 0x2002: writeChar4(4バイト出力)
  • 0x2004: writeChar8(8バイト出力)
  • 0x2006: readInput(1バイト入力)
  • 0x2100: SHOW_KEYBOARD(キーボード表示制御)

サンプルCコード(抜粋)

  • 画面への出力・入力受付の例を提供
  • 数字・英字キーボードの切り替え制御
  • 無限ループでユーザー入力を待機
  • 入力値をエコーバック表示

クレジット・参考資料

  • Jane Ori:CPU Hackの着想元
  • Soo-Young Lee:8086命令リファレンス
  • mlsite.net:8086オペコードマップ
  • crtc-demos, tkchia:gcc-ia16関連
  • polly:ARMやハードウェアの知識提供
  • cohosters:CSS学習のきっかけ

動作環境

  • 最新のChromium系ブラウザ 推奨
  • 対応外ブラウザではデモが動作しない場合あり

まとめ

  • CSSだけでx86エミュレータを実装 するという前例のない試み
  • JavaScript不要・HTML最小限 でプログラム実行を可能に
  • カスタムI/Oやビルド手順 も明確にドキュメント化
  • 遊び・学習・アート のためのプロジェクト
  • 技術的な限界を楽しむための 発想の転換例

Hackerたちの意見

CSSがチューリング完全である必要なんて全くないよ。まったく。とはいえ、よくやったね。

CSSは、JavaScriptがスタイリングコンポーネントを開発できなかったから存在していると言えるのかな?WebAssemblyが正しい方向に進んでると思うけど、ECMAScriptもCSSも、もっとシンプルなバイトコードのような中間言語の構文に退化する必要があったんじゃないかな。複雑な言語をサポートするブラウザはいつも悪いアイデアだったし、必要なのは機能のサポート、アクセス、セキュリティのプリミティブだと思う。WasmはJavaScriptを置き換えてないけど、私の知る限り、ブラウザのためのWasm仕様はJavaScript(理想的にはCSS)をWasm経由で実装することを要求してないんだよね。CSSとJavaScriptを単純化して仕様化する代わりに、ブラウザは複雑な機能の層を重ねていった。ブラウザがフロントエンドコードを書くための言語を定義して規制すべきだという考えはもう終わりにすべきだね。

CSSがチューリング完全である必要は全くない。ちょっと反論したいな — 実用的な点ではもちろんそうだけど、「なんでそんなことするの?」って質問には。こういうプロジェクトの面白いところは、どのCSS機能がチューリング完全性の閾値を越えるのかを正確に特定させるところだよ。CSSはほぼ偶然にそこに到達したんだ:セレクタは状態に対するパターンマッチングを提供し、:hoverのような擬似クラスは反応的な状態変化を与え、兄弟/子孫コンビネータはその変化を空間的に伝播させる。最小限の実用的なチューリングマシンは、全く別の目的で設計された機能から生まれる。それが、Minecraftのレッドストーンやコナウェイのライフゲームでコンピュータを作る理由でもある — その演習は「計算」が実際に何を必要とするかを明らかにする。あと、READMEに書いてあったように、ホバーインタラクションなしで安定したクロックを得るためのエンジニアリングは本当に賢い仕事だね。

@function [0]がもっと広くサポートされるようになったら、他のChrome以外のブラウザでもこれが使えるようになるのが楽しみだね? [0]: https://caniuse.com/wf-function

いくつかの要素に依存してるけど、@functions、if()文、コンテナスタイルクエリが主なものだね。

おお!全然関係ないけど、驚くことでもないね:ゼロデイCSS:CVE-2026-2441が実際に存在するらしい - https://news.ycombinator.com/item?id=47062748 - 2026年2月(233コメント)

実はChromeにCSSのCVE[0]があるんだけど、変更履歴には「Animation内」としか書かれてなくて、「CSS内」じゃなかったから、面白い話や見出しにはならなかったよ :c [0] https://chromereleases.googleblog.com/2025/06/stable-channel...

それがあまり関係ないとは思わないな。システムを必要以上に複雑にすると(CSSがまさにそうだけど)、脆弱性のリスクが指数的に増えるのは明らかだよね。

それは、JSに公開されるCSSインターフェースのC++実装の中の話で、CSSからのエクスプロイトではなかったよ。

信じられない成果だね。でもCSSの進展はひどい。CSSはチューリング完全になってはいけないし、他のDSLも同様だよ。

CSSはチューリング完全になってはいけない。どんなDSLもそうだろ。もうしばらくそうじゃなかったっけ? まあ、君に同意するけど、ちょっと遅すぎる気がする。

それが問題なんだよね。DSLはいつもチューリング完全になっちゃう。カバーできてないユースケースが必ずあるから。

ジェーン・オリのCPUハックにあるようなホバー式の時計は速くて安定してるけど、マウスを画面に置いておく必要があるから、理由はどうあれ「チューリング完全とは言えない」と主張する人もいるんだ。だからこのデモはユーザー入力なしで完全に機能するようにしたかったんだ。あのホバー時計の投稿は2023年のもので、「一部の人がカウントしないと言っている」という投稿は2022年のものだね。おそらく、論理を進めるために何千ものボックスをチェックさせるようなものについて話してたんだろうね。とにかく、すごい進展だね。

FAQの不一致について触れるべきか迷ったんだけど、短くて読みやすくしたかったんだ。昔から、CSSにはチューリング完全性や他のプログラム的な特性を証明するデモがあったけど、それがユーザー入力を必要とするものとして軽視されてきたんだよね。コメントが出た時点でのデモは、まさに「同じ場所を何度もクリックする」レベルで、要するに時計を提供しているだけだった。Jane Oriのハックの後の議論を見ていると、特定の画面の部分にマウスをホバーさせるだけでも、CSSはプログラミング言語じゃないって主張する人がまだ多いんだよね。

複雑な気持ちだな。一方ではすごいと思うけど、もう一方ではCSSが「JavaScript 2」になっていくのが心配だよ。

JSが無効でも、ページにクリプトマイナーを埋め込めるようになったね!/s

これにはインスパイアされるね。これを実現するために最も重要な機能は何だと思う? calcとifがかなりの部分を担っているみたいだけど、新しい関数の構文が命令の検索を可能にしているんだよね。

まさに「考えるべきかどうかを考えなかった」って感じだね。

おそらく考えたんだろうけど、楽しいと思ったんじゃないかな。先週、TempleOSにIPv6サポートを実装するという楽しいプロジェクトがあったんだ。やるべきかどうか考えたけど、絶対にやらないと決めた。Claudeに計画を立てるように頼んだんだ。ZealOSを参照し始めて、TempleOSのフォークで既に機能するTCPスタックがあるってことが分かった。その時点で、もう楽しくないって判断して、諦めたんだ。

すごいね。horsleのデモを見て思ったんだけど、ランダムなバイトを返す仮想メモリアドレス(または非8086 RAND命令)を追加するのってどれくらい難しいんだろう?(原理的にワードルを動かすためにランダムな値を選べるようになる)CSSのrandom()はSafariだけがサポートしてるみたいだけど、Chromeで使えるサイドチャネルとかあるのかな?(ユーザー入力のタイミングを測るのがいいかも)

それはめっちゃ簡単だよ。考えてたんだけど、アニメーションが異常な速さで動く@propertyを作るのが一番手っ取り早い。そうすれば(なんとなく)ランダムなビットをサンプリングできる。

これはクールなデモだけど、CSSが今や複雑すぎるかもしれないって思わせるね。スタイリング言語でCPUをエミュレートできる理由って何?視覚的スタイリングにチューリング完全な言語を使うことで何が得られるのか、よくわからないな。

CSSについてあまり詳しくないけど、チューリング完全性は意図せずにシステムに現れることで有名だよね。チューリング完全になるのはそんなに難しくない — 無制限の読み書きメモリと分岐や条件付き再帰があれば、だいたいそこに到達する。例えば、マジック:ザ・ギャザリング(カードゲーム)はチューリング完全なんだ: https://arxiv.org/abs/1904.09828 。クリーチャートークンをメモリとして使ったり、さまざまなゲームメカニクスでフロー制御を行ったりできる。これはデザイナーの意図だったのかな?おそらくそうじゃないだろうね…