VMトランスレーター / Code_Writerを作る / 和、差、論理積、論理和
Chapter 7
今度は和、差、論理積、論理和を追加する。
class Code_Writer: def __init__(self, file_path): self.file = open(file_path, "w") self.calcs = { "neg": "M=-D", "not": "M=!D", "add": "M=D+M", "sub": "M=M-D", "and": "M=D&M", "or": "M=D|M",} def write_arithmetic(self, command): # まずスタックポインタをデクリメントして、 # 最後尾値(今のスタックポインタの位置にある値)をDレジスタに取り出して、 self.__decrement_pointer("SP") self.__load_d_with_ram_ram_pointer("SP") # 単項演算子の場合: # 演算結果を今のスタックポインタの位置に上書きして、 if self.__is_unary_op(command): self.file.write(self.calcs[command] + "\n") # 二項演算子の場合: # さらにスタックポインタをデクリメントし、 # スタックポインタの指し示すアドレスをAレジスタに取り出し、 elif self.__is_binary_op(command): self.__decrement_pointer("SP") self.file.write("A=M\n") # そのアドレスに格納してある値(すなわち今のスタックポインタの位置にある値)と、先に取り出したDレジスタの値との演算結果を # 今のスタックポインタの位置に上書きして、 self.file.write(self.calcs[command] + "\n") # 最後にスタックポインタをインクリメントする。 self.__increment_pointer("SP") def write_push_pop(self, command, segment, index): if command == "C_PUSH": if segment == "constant": self.__load_d_with_immediate_value(index) # 即値をDレジスタに読み込んで、 self.__load_ram_ram_pointer_with_d("SP") # それを、今のスタックポインタの位置に書き込んで、 self.__increment_pointer("SP") # 最後にスタックポインタをインクリメントする。 def write_halt(self): self.file.write("@HALT\n") self.file.write("(HALT)\n") self.file.write("0;JMP\n") def close(self): self.file.close() ######################################################################## def set_pointer(self, name, val): self.file.write("@" + str(val) + "\n") self.file.write("D=A\n") self.file.write("@" + name + "\n") self.file.write("M=D\n") def __decrement_pointer(self, pointer_name): self.file.write("@" + pointer_name + "\n") self.file.write("M=M-1\n") def __increment_pointer(self, pointer_name): self.file.write("@" + pointer_name + "\n") self.file.write("M=M+1\n") def __load_d_with_immediate_value(self, immediate_value): self.file.write("@" + str(immediate_value) + "\n") self.file.write("D=A\n") def __load_d_with_ram_ram_pointer(self, pointer_name): self.file.write("@" + pointer_name + "\n") self.file.write("A=M\n") self.file.write("D=M\n") def __load_ram_ram_pointer_with_d(self, pointer_name): self.file.write("@" + pointer_name + "\n") self.file.write("A=M\n") self.file.write("M=D\n") def __is_unary_op(self, command): return command == "neg" or command == "not" def __is_binary_op(self, command): return not self.__is_unary_op(command) ######################################################################## if __name__ == "__main__": c = Code_Writer("Test.asm") c.set_pointer("SP", 256) c.write_push_pop("C_PUSH", "constant", 7) c.write_push_pop("C_PUSH", "constant", 8) c.write_arithmetic("add") c.write_push_pop("C_PUSH", "constant", 9) c.write_arithmetic("sub") c.write_push_pop("C_PUSH", "constant", 10) c.write_arithmetic("and") c.write_push_pop("C_PUSH", "constant", 11) c.write_arithmetic("or") c.write_arithmetic("not") c.write_arithmetic("neg") c.write_halt() c.close() # 7+8=15 # 15-9=6 (= 0b0_0110) # 0b0_0110 && 0b0_1010 = 0b0_0010 # 0b0_0010 || 0b0_1011 = 0b0_1011 (= 0d11) # not(0b0_1011) = 0b1_0100 # neg(0b1_0100) = 0b0_1100 (= 0d12)
実行結果: