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)

実行結果: