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 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 write_commands(commands, hack_file, symbolTable, var_sym_start): for command in commands: # For all commands if command.type == 'A_Command': # In the case of A_Commands label = command.cmd_string # ...grab the A_Command itself if (not label.isdigit()) and (label not in symbolTable.keys()): # Check if the A_Command is a variable label, and not already entered into symbolTable symbolTable[label] = var_sym_start # Enter new Variable Label into Symobl Table var_sym_start = var_sym_start + 1 # Set memory location of next Variable Symbol if command.cmd_string in symbolTable.keys(): # If the A_Command is a Variable Symbol for a RAM address address = int(symbolTable[command.cmd_string]) # Grab the corresponding decimal address else: address = int(command.cmd_string) # Otherwise, get the decimal address explicitly from the A_Command address = bin(address)[2:] # Turn the address from decimal to binary address = (16-len(address))*'0' + address # Pad the binary address with zeros so it is 16 bits hack_file.write(address + '\n') # Write the address specified by the A_Command to the .hack file elif command.type == 'C_Command': # In the case of a C_Command if '=' in command.cmd_string: # If there is an equal sign in the command: dest = command.cmd_string.partition('=')[0] # Get the dest bits cmp = command.cmd_string.partition('=')[2] # Get the cmp bits jmp = None # Get the jmp bits (note that when there is an = in the C_Command, the jump bits are '000' elif ';' in command.cmd_string: # Same thing if there is an ';' in the command, except the dest bits are '000' dest = None cmp = command.cmd_string.partition(';')[0] jmp = command.cmd_string.partition(';')[2] hack_file.write('111' + code.cmp(cmp) + code.dest(dest) + code.jmp(jmp) + '\n') # Write the C_Command to the .hack file.
def test_dest(self): self.assertEqual(code.dest(None), '000') self.assertEqual(code.dest('M'), '001') self.assertEqual(code.dest('D'), '010') self.assertEqual(code.dest('MD'), '011') self.assertEqual(code.dest('A'), '100') self.assertEqual(code.dest('AM'), '101') self.assertEqual(code.dest('AD'), '110') self.assertEqual(code.dest('AMD'), '111')
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")
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
def cmd(dest, comp, jump): return '111' + code.comp(comp) + code.dest(dest) + code.jump(jump)
while 1: if prsInstance.commandType() == "A_COMMAND": A_binLine = bin(int(prsInstance.symbol()))[2:].zfill(16) 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()
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")
#!/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
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:]