5
8ビット仮想マシン
バックグラウンド 私は古い8ビット6502チップが好きです。6502マシンコードでPPCGの問題を解決するのは楽しいことです。しかし、単純であるべきいくつかのこと(データの読み取りやstdoutへの出力など)は、マシンコードで行うのは不必要に面倒です。だから、私の頭の中には大まかなアイデアがあります。6502に触発された独自の8ビット仮想マシンを発明します。何かを実装し始めて、VMの設計が最小限に抑えられている場合、これ自体が素晴らしい挑戦であるかもしれないことに気付きました:) 仕事 次の仕様に準拠する8ビット仮想マシンを実装します。これはcode-golfであるため、バイト数が最も少ない実装が優先されます。 入力 実装には、次の入力が必要です。 単一の符号なしバイトpc、これは初期プログラムカウンター(VMが実行を開始するメモリ内のアドレス、0ベース) 256エントリの最大長を持つバイトのリスト。これは仮想マシンのRAM(初期コンテンツを含む) この入力は、適切な形式で入力できます。 出力 VMが終了した後のRAMの最終的な内容であるバイトのリスト(以下を参照)。最終的に終了することにつながる入力のみを取得すると仮定できます。賢明な形式はすべて許可されます。 仮想CPU 仮想CPUには 8ビットプログラムカウンター、 呼ばれる8ビットアキュムレータレジスタAと という8ビットのインデックスレジスタX。 3つのステータスフラグがあります。 Z -何らかの操作の結果、ゼロフラグが設定された 0 N -負のフラグは、何らかの操作の結果が負の数になった後に設定されます(結果のビット7が設定されます) C -キャリーフラグは、結果の「欠落」ビットの加算とシフトによって設定されます スタート時には、フラグが全てクリアされ、プログラムカウンタは、与えられた値との内容に設定されているAとX不定です。 8ビット値は、 符号なしの範囲の整数[0..255] 範囲の符号付き整数、2の補数[-128..127] コンテキストに応じて。操作がオーバーフローまたはアンダーフローすると、値は折り返されます(また、追加の場合、キャリーフラグが影響を受けます)。 終了 仮想マシンは次の場合に終了します HLT命令に到達します 存在しないメモリアドレスがアクセスされた プログラムカウンターはメモリ外で実行されます(VMに256バイトのメモリがすべて与えられてもラップアラウンドしないことに注意してください) ドレッシングモード 暗黙的 -命令には引数がありません。オペランドは暗黙的です 即時 -オペランドは命令の直後のバイトです relative-(分岐のみ)命令が署名された後のバイト(2の補数)。分岐が行われた場合にプログラムカウンターに追加するオフセットを決定します。0次の命令の場所です absolute-命令の後のバイトは、オペランドのアドレスです インデックス付き -命令プラスX(レジスタ)の後のバイトは、オペランドのアドレスです 説明書 各命令はオペコード(1バイト)で構成され、アドレッシングモードでは、immediate、relative、absolute、およびindexedの2番目の引数バイトです。仮想CPUが命令を実行すると、それに応じて(1または2)プログラムカウンターをインクリメントします。 ここに示されているすべてのオペコードは16進数です。 LDA -オペランドをロードする A オペコード:即時:00、絶対:02、インデックス付き:04 …