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増やします。
Add、Sub、Load、Store は、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 を送出してください。