コンテンツにスキップ

021: SSCを定義する

ヒント / 解答

難易度: ☆☆☆

問題

SSC(SlowScanComputer)をPythonで定義してください。 この問題で作る関数は、後続のSSCプログラミング問題で使います。

SSCは、32語のメモリ、プログラムカウンタ pc、Accumulator acc、入力列、出力列を持つ小さな計算機です。 命令は0以上255以下の8ビット整数で表します。 上位3ビットは命令の種類を表すopcodeです。 下位5ビットは番地またはシフト量を表すoperandです。 operandは0以上31以下の整数です。

命令は次の8種類です。

ニーモニック opcode operandの意味
Jump 000 分岐先の番地
Add 001 加算する値の番地
Sub 010 減算する値の番地
Load 011 読み込む値の番地
Store 100 書き込む番地
Read 101 入力を書き込む番地
Write 110 出力する値の番地
Shift 111 左シフトするビット数

次の名前を実装してください。

  • INSTRUCTIONS:命令名からopcodeを引ける辞書
  • encode_instruction(name, operand):命令名とoperandを8ビット命令へ変換する関数
  • decode_instruction(instruction):8ビット命令を (命令名, operand) へ変換する関数
  • assemble_line(line)"Load 7" のような1行のアセンブリ表記を8ビット命令へ変換する関数
  • disassemble_instruction(instruction):8ビット命令を1行のアセンブリ表記へ変換する関数
  • make_machine(program=None, inputs=None):SSCの初期状態を作る関数
  • step(machine):SSCを1命令だけ進める関数
  • run(program, inputs=None, max_steps=1000):SSCを停止まで実行し、出力値のリストを返す関数

制約

  • encode_instruction は、未知の命令名に KeyError を送出してください。
  • encode_instruction は、範囲外のoperandに ValueError を送出してください。
  • decode_instruction は、0以上255以下でない命令に ValueError を送出してください。
  • assemble_line は、行頭と行末の空白を無視してください。
  • assemble_line は、; 以降をコメントとして無視してください。
  • assemble_line は、空行とコメントだけの行には None を返してください。
  • Stop は、Jump 0 の別名として扱ってください。
  • make_machine は、program をメモリの先頭から順に置き、残りを0で埋めてください。
  • Read で入力が空の場合は EOFError を送出してください。
  • run は、max_steps 回実行しても停止しない場合に RuntimeError を送出してください。
  • データはPython整数として扱い、8ビットに丸めないでください。

命令の動作

Jump 0 は停止命令です。 Jump n は、Accumulatorが正のときだけ n 番地へ分岐します。 分岐しない命令では、pc を1増やします。

AddSubLoadStore は、operandをメモリ番地として使います。 Read は、入力列の先頭をoperand番地へ書き込みます。 Write は、operand番地の値を出力列へ追加します。 Shift は、Accumulatorをoperandビットだけ左シフトします。

>>> decode_instruction(0b01100111)
('Load', 7)
>>> encode_instruction("Load", 7)
103
>>> assemble_line("  Shift 1  ; double")
225
>>> disassemble_instruction(0)
'Stop'
>>> program = [
...     assemble_line("Read 10"),
...     assemble_line("Write 10"),
...     assemble_line("Stop"),
... ]
>>> run(program, [42])
[42]
>>> run([assemble_line("Stop")])
[]

発展

pc が0以上31以下でない場合に、step から ValueError を送出してください。