VMトランスレーター / Code_Writerを作る / 比較演算子
Chapter 7
今度は比較演算子。
class Code_Writer: def __init__(self, file_path): self.file = open(file_path, "w") self.label_count = 0 self.calcs = { "neg":"M=-D", "not":"M=!D", "add":"M=D+M", "sub":"M=M-D", "and":"M=D&M", "or":"M=D|M",} self.jumps = { "eq":"D;JEQ", "gt":"D;JGT", "lt":"D;JLT",} 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レジスタの値を引いて、 if self.__is_comparison_op(command): self.file.write("D=M-D\n") true_label = "TRUE" + str(self.label_count) end_label = "END" + str(self.label_count) self.label_count += 1 # 引き算の結果がtrueなら(イ)に飛んで、 self.file.write("@" + true_label + "\n") # ここでどうしてもAレジスタの値が変化する。 self.file.write(self.jumps[command] + "\n") # 引き算の結果がfalseなら、 # ここに来る前にAレジスタの値が変化したので再度スタックポインタの位置を取得して、 # 今のスタックポインタの位置に0を書き込んで、 # (ロ)に飛んで、抜ける。 self.__load_a_with_pointer("SP") self.file.write("M=0\n") self.file.write("@" + end_label + "\n") self.file.write("0;JMP\n") # (イ) # ここに来る前にAレジスタの値が変化したので再度スタックポインタの位置を取得して、 # 今のスタックポインタの位置に-1 (全ビット1)を書き込んで、 # 抜ける。 self.file.write("(" + true_label + ")\n") self.__load_a_with_pointer("SP") self.file.write("M=-1\n") # (ロ) self.file.write("(" + end_label + ")\n") # 和、差、論理積、論理和の場合: # 今のスタックポインタの位置にある値と先に取り出したDレジスタの値との演算結果を # 今のスタックポインタの位置に上書きして、 else: 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_a_with_pointer(self, pointer_name): self.file.write("@" + pointer_name + "\n") self.file.write("A=M\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) def __is_comparison_op(self, command): return command == "eq" or command == "gt" or command == "lt" ######################################################################## if __name__ == "__main__": c = Code_Writer("Test.asm") c.set_pointer("SP", 256) c.write_push_pop("C_PUSH", "constant", 100) c.write_push_pop("C_PUSH", "constant", 101) c.write_arithmetic("eq") c.write_push_pop("C_PUSH", "constant", 200) c.write_push_pop("C_PUSH", "constant", 200) c.write_arithmetic("eq") c.write_push_pop("C_PUSH", "constant", 300) c.write_push_pop("C_PUSH", "constant", 301) c.write_arithmetic("gt") c.write_push_pop("C_PUSH", "constant", 401) c.write_push_pop("C_PUSH", "constant", 400) c.write_arithmetic("gt") c.write_push_pop("C_PUSH", "constant", 500) c.write_push_pop("C_PUSH", "constant", 501) c.write_arithmetic("lt") c.write_push_pop("C_PUSH", "constant", 600) c.write_push_pop("C_PUSH", "constant", 600) c.write_arithmetic("lt") c.write_halt() c.close()
実行結果: