def second_pass(commands, symbol_table, output_file): """ Pass through the assembly program's commands, parse each line, and translate commands into binary form, and write to .hack file that CPU can load in ROM. """ RAM_counter = 16 # 16 is next free RAM address after predefined symbols with open(output_file, 'a') as f: for command in commands: c_type = parser.command_type(command) if c_type == "A_COMMAND": chars = parser.symbol(command) # Test whether chars in the A-instruction are symbol or number results = char_test(chars, symbol_table, RAM_counter) chars = results['c'] symbol_table = results['st'] RAM_counter = results['ram'] # Translate chars into a instruction and write to f f.write(code.get_a_instruction(chars) + '\n') elif c_type == "C_COMMAND": jump_mnemonic = parser.jump(command) dest_mnemonic = parser.dest(command) comp_mnemonic = parser.comp(command) f.write("111" + code.comp(comp_mnemonic) + code.dest(dest_mnemonic) + code.jump(jump_mnemonic) + '\n')
def main(): #Takes in filename newfile = input("Which asm file do you want me to read (don't include .asm)? ") #Opens and reads file Parser.Parser(newfile + ".asm") #Removes whitespace/fixes labels firstPass() #Fixes variables secondPass() global finalOut finalOut = [] #While more commands, determine if A or C and add to finalOut array while Parser.hasMoreCommands(): Parser.categorize() if Parser.A: global binnum binnum = str(code.AInstruction()) addA() else: global comp comp = str(code.comp()) global dest dest = str(code.dest()) global jump jump = str(code.jump()) addC() Parser.advance() #Writes to hack file hack = open(newfile + ".hack", "w") hack.writelines(finalOut)
def assemble(fileName): import assemblerParser from assemblerParser import Parser import code import symbolTable from symbolTable import SymbolTable WORD_SIZE = 16 #words are 16 bits long currentDataAddr = 16 file = open(fileName, 'r') parser = Parser(file) table = SymbolTable() #Symbol generating pass counter = 0 while (parser.hasMoreCommands()): parser.advance() if (parser.commandType() == Parser.L_COMMAND): table.addEntry(parser.symbol(), counter) else: counter += 1 newFileName = fileName[:fileName.find(".", 1)] + ".hack" outputFile = open(newFileName, 'w') #Code generating pass file = open(fileName, 'r') parser = Parser(file) while parser.hasMoreCommands(): parser.advance() output = "BLANK" if (parser.commandType() == Parser.C_COMMAND): output = "111" + code.comp(parser.comp()) + code.dest( parser.dest()) + code.jump(parser.jump()) outputFile.write(output + "\n") elif parser.commandType() == Parser.A_COMMAND: symbol = parser.symbol() try: symbol = int(symbol) except: pass if type(symbol) is int: binVal = bin( int(symbol) )[2:] #the slice is because the value will be in the form 0b# so we need to remove the 0b elif table.contains(symbol): binVal = bin(table.getAddress(symbol))[2:] else: table.addEntry(symbol, currentDataAddr) binVal = bin(currentDataAddr)[2:] currentDataAddr += 1 output = "0" * (WORD_SIZE - len(binVal)) + binVal outputFile.write(output + "\n") elif parser.commandType() == Parser.L_COMMAND: pass else: print("Bad Munkey!") print("Original is " + parser.current() + " BIN: " + output + "COMP: " + parser.comp())
def assemble(fileName): import assemblerParser from assemblerParser import Parser import code import symbolTable from symbolTable import SymbolTable WORD_SIZE = 16 #words are 16 bits long currentDataAddr = 16 file = open(fileName, 'r') parser = Parser(file) table = SymbolTable() #Symbol generating pass counter = 0 while(parser.hasMoreCommands()): parser.advance() if(parser.commandType() == Parser.L_COMMAND): table.addEntry(parser.symbol(), counter) else: counter += 1 newFileName = fileName[:fileName.find(".", 1)] + ".hack" outputFile = open(newFileName, 'w') #Code generating pass file = open(fileName, 'r') parser = Parser(file) while parser.hasMoreCommands(): parser.advance() output = "BLANK" if(parser.commandType() == Parser.C_COMMAND): output = "111" + code.comp(parser.comp()) + code.dest(parser.dest()) + code.jump(parser.jump()) outputFile.write(output + "\n") elif parser.commandType() == Parser.A_COMMAND: symbol = parser.symbol() try: symbol = int(symbol) except: pass if type(symbol) is int: binVal=bin(int(symbol))[2:] #the slice is because the value will be in the form 0b# so we need to remove the 0b elif table.contains(symbol): binVal = bin(table.getAddress(symbol))[2:] else: table.addEntry(symbol, currentDataAddr) binVal = bin(currentDataAddr)[2:] currentDataAddr += 1 output = "0" * (WORD_SIZE - len(binVal)) + binVal outputFile.write(output + "\n") elif parser.commandType() == Parser.L_COMMAND: pass else: print("Bad Munkey!") print("Original is " + parser.current() + " BIN: " + output + "COMP: " + parser.comp())
def parseCommand(cmd): if commandType(cmd) == 'A_COMMAND': smb = int(symbol(cmd)) return code.decimalToBinary(smb) if commandType(cmd) == 'C_COMMAND': cmdDest = dest(cmd) cmdComp = comp(cmd) cmdJump = jump(cmd) return '111' + code.comp(cmdComp) + code.dest(cmdDest) + code.jump( cmdJump) return cmd
def main(filename): outputFilename = os.path.splitext(filename)[0]+".hack" st = symbol_table.SymbolTable() # First pass store all LABELS p = parser.Parser(filename) p.advance() instructionCount = 0 while p.hasMoreCommands(): commandType = p.commandType() if p.commandType() == command_types.L_COMMAND: symbol = p.symbol() st.addEntry(symbol, instructionCount) else: instructionCount += 1 p.advance() # Second pass n = 16 p = parser.Parser(filename) p.advance() while p.hasMoreCommands(): command = "" if p.commandType() == command_types.A_COMMAND: symbol = p.symbol() address = "" if st.contains(symbol): address = st.getAddress(symbol) elif symbol.isdigit(): address = symbol else: st.addEntry(symbol, n) address = n n += 1 command = format(int(address), '#018b')[2:] elif p.commandType() == command_types.C_COMMAND: command = "111" + code.comp(p.comp()) + code.dest(p.dest()) + code.jump(p.jump()) if bool(command): with open(outputFilename, 'a') as outFile: outFile.write(command+"\n") p.advance()
def get_code(command): command = clear_trash(command) output = "" if parser.command_type(command) == "A_COMMAND": output = "0" + address_of(parser.symbol(command)) + "\n" elif parser.command_type(command) == "L_COMMAND": pass elif parser.command_type(command) == "C_COMMAND": dest = code.dest(parser.dest(command)) jump = code.jump(parser.jump(command)) comp = code.comp(parser.comp(command)) output = "111" + comp + dest + jump + "\n" else: raise ValueError("Code not a valid command: {0}".format(command)) return output
def assemble_command(parser: parse.Parser, table: symbol.SymbolTable) -> str: """convert the current command into a binary string""" if parser.command_type() == parse.CmdType.A: symbol = parser.symbol() num = resolve_symbol(symbol, table) return "{:016b}".format(num) elif parser.command_type() == parse.CmdType.C: #C command op = "1" dest_sym = parser.dest() dest = code.dest(dest_sym) comp_sym = parser.comp() comp = code.comp(comp_sym) jump_sym = parser.jump() jump = code.jump(jump_sym) return "111{comp}{dest}{jump}".format(dest=dest, comp=comp, jump=jump) else: raise RuntimeError("Cannot assemble pseudo-command")
def cmd(dest, comp, jump): return '111' + code.comp(comp) + code.dest(dest) + code.jump(jump)
command_line) # Clean comments and whitespace if len(command_line) > 0: if commandtype(command_line) == "A_Command": if not command_line[1:].isnumeric(): if not command_line[1:] in symbol_table: symbol_table[command_line[1:]] = convert_binary( str(variable_memory_count)) variable_memory_count += 1 address = symbol_table[command_line[1:]] else: address = convert_binary(command_line[1:]) outputline = outputline + "0" + address outputlist.append(outputline) elif commandtype(command_line) == "C_Command": dest = "" jump = "" comp = "" if command_line.find(";") > 0: comp, sep, jump = command_line.partition(";") else: dest, sep, comp = command_line.partition("=") outputline = outputline + "111" + code.comp(comp) + code.dest( dest) + code.jump(jump) outputlist.append(outputline) #Write to a file filename, sep, extension = assembly_file.name.partition(".") filename = filename + ".hack" with open(filename, "w+") as outputfile: for outputline in outputlist: outputfile.write(outputline + "\n")
elif parse.commandType() == "L_COMMAND": symbolTable.addEntry(parse.symbol(), ROMaddress) parse.currentCommandCounter = 0 #The current command needs to be set to the start so the instrunction can be parsed and translated RAMaddress = 16 while parse.hasMoreCommands(): parse.advance() if parse.commandType() == "A_COMMAND": #If A_COMMAND then translated instruction is a 0 followed by symbol address (15 bits) if parse.symbol().isdigit(): f.write("0%s\n" %(format(int(parse.symbol()), '015b'))) #If the A_COMMAND does not use a symbol then convert to binary else: if symbolTable.contains(parse.symbol()): f.write("0%s\n" %(format(int(symbolTable.getAddress(parse.symbol())), '015b'))) #If symbol exists in the symbol table then use it associated value else: symbolTable.addEntry((parse.symbol()), str(RAMaddress)) f.write("0%s\n" %(format(int(symbolTable.getAddress(parse.symbol())), '015b'))) #If the symbol does not exist then add it to the symbol table RAMaddress += 1 elif parse.commandType() == "C_COMMAND": a = "0" if "M" in parse.comp(): a = "1" f.write("111%s%s%s%s\n" %( #C_COMMAND is as follows: 111 a, # a is 0 if comp using A, 1 if using M code.comp(parse.comp()), # c1..c6 Comp bits code.dest(parse.dest()), # d1..d3 Dest bits code.jump(parse.jump()) # j1..j3 Jump bits )) # Put together is: 1 1 1 a c1 c2 c3 c4 c5 c6 d1 d2 d3 j1 j2 j3 f.close
#!/usr/bin/env python import sys from parser import Parser import code in_file = sys.argv[1] with open(in_file, 'r') as f: contents = f.read() commands = [] for line in contents.split('\n'): if not line or line.startswith('//'): continue commands.append(line) p = Parser(commands) while p.has_more_commands(): p.advance() command_type = p.command_type if command_type == 'A_COMMAND': print code.integer(p.symbol) elif command_type == 'C_COMMAND': print '111' + code.comp(p.comp) + code.dest(p.dest) + code.jump(p.jump) elif command_type == 'L_COMMAND': pass
def test_comp(self): self.assertEqual(code.comp('0'), '0101010') self.assertEqual(code.comp('1'), '0111111') self.assertEqual(code.comp('-1'), '0111010') self.assertEqual(code.comp('D'), '0001100') self.assertEqual(code.comp('A'), '0110000') self.assertEqual(code.comp('!D'), '0001101') self.assertEqual(code.comp('!A'), '0110011') self.assertEqual(code.comp('-D'), '0001111') self.assertEqual(code.comp('-A'), '0110011') self.assertEqual(code.comp('D+1'), '0011111') self.assertEqual(code.comp('A+1'), '0110111') self.assertEqual(code.comp('D-1'), '0001110') self.assertEqual(code.comp('A-1'), '0110010') self.assertEqual(code.comp('D+A'), '0000010') self.assertEqual(code.comp('D-A'), '0010011') self.assertEqual(code.comp('A-D'), '0000111') self.assertEqual(code.comp('D&A'), '0000000') self.assertEqual(code.comp('D|A'), '0010101') self.assertEqual(code.comp('M'), '1110000') self.assertEqual(code.comp('!M'), '1110001') self.assertEqual(code.comp('-M'), '1110011') self.assertEqual(code.comp('M+1'), '1110111') self.assertEqual(code.comp('M-1'), '1110010') self.assertEqual(code.comp('D+M'), '1000010') self.assertEqual(code.comp('D-M'), '1010011') self.assertEqual(code.comp('M-D'), '1000111') self.assertEqual(code.comp('D&M'), '1000000') self.assertEqual(code.comp('D|M'), '1010101')
bin_codes.append(A_binLine) print(A_binLine) prsInstance.advance() #write to a .hack file elif prsInstance.commandType() == "L_COMMAND": pass #try to write the program when I reach the next step (symbolic table) elif prsInstance.commandType() == "C_COMMAND": dest_mnic = prsInstance.dest() dest_bin = code.dest(dest_mnic) comp_mnic = prsInstance.comp() comp_bin = code.comp(comp_mnic) jump_mnic = prsInstance.jump() jump_bin = code.jump(jump_mnic) C_binLine = "111" + comp_bin + dest_bin + jump_bin bin_codes.append(C_binLine) print(C_binLine) prsInstance.advance() elif prsInstance.commandType() == "COMMENT": #print("This is a comment") prsInstance.advance() elif prsInstance.commandType() == "BLANK": #print("This is a blank")
newFilename = filename.split('.')[0] + '.hack' outputFile = open(newFilename, 'w') #Second pass to create code WORD_SIZE = 16 currentMemoryLocation = 16 Parser = assemblerParser.parser(filename) while Parser.hasMoreCommands(): Parser.advanceCommand() output = '' if Parser.commandType() == Parser.C_COMMAND: output = '111' + code.comp(Parser.comp()) + code.dest(Parser.dest()) + code.jump(Parser.jump()) + '\n' outputFile.write(output) elif Parser.commandType() == Parser.A_COMMAND: symbol = Parser.symbol() try: symbol = int(symbol) except: pass if type(symbol) is int: binVal = bin(int(symbol))[2:] elif Table.contains(symbol): binVal = bin(Table.getAddress(symbol))[2:] else: Table.addEntry(symbol, currentMemoryLocation) binVal = bin(currentMemoryLocation)[2:]