#!/usr/bin/python # Simple assmebler.py # this code is based on "https://www.openbookproject.net/courses/python4fun/_downloads/assembler.py" import sys, string codes={"BNE":0, "ADD":1, "SUB":2, "LDI":3, "LDW":4, "STW":5 , ".fill":99} lookup={"$t0":0, "$t1":1, "$t2":2, "$t3":3, "$t4":4, "$t5":5, "$t6":6, "$t7":7} def getVal (s): "return numeric value of a symbol or number" if not s: return 0 a = lookup.get(s) if a == None: return int(s) else: # print "found a symbol in a get value", a return int(a) def pass1(program) : "determine addresses for labels and add to the lookup dictionary" global lookup pReg = 0 for lin in program : # print lin flds = string.split(lin) # print "****** %s "% flds if not flds : continue if codes.get(flds[0]) == None: # found a symbol symb =flds[0] # print "** found a symbol ", symb, pReg lookup[symb] = pReg # if len(flds) > 1: pReg = pReg+1 # else: pReg = pReg + 1 def bin(a, digit): s ='' t ={'0':'000','1':'001','2':'010','3':'011', '4':'100','5':'101','6':'110','7':'111'} nt={'0':'000','1':'111','2':'110','3':'101', '4':'100','5':'011','6':'010','7':'001'} if (a <0) : for c in oct(a)[2:]: # print "---c is %s" % (c) s+=nt[c] if (len(s) < digit): for i in range (digit-len(s)): s='1'+s else: for c in oct(a)[1:]: s+=t[c] if (len(s) < digit): for i in range (digit-len(s)): s='0'+s # print "---a is %d s is %s" % (a, s) return s def toHex(a): s ='' t ={'0000':0, '0001':1, '0010':2, '0011':3, '0100':4, '0101':5, '0110':6, '0111':7, '1000':8, '1001':9, '1010':10, '1011':11, '1100':12, '1101':13, '1110':14, '1111':15} for i in range (4): num1 = t[a[(0+i*4):(4+4*(i))]] s = s + "%x"%(num1) return s def assemble (flds, pReg): "assemble instruction to machine code" opval = codes.get(flds[0]) if opval == None: if opval == None: return 0 ## no line at all if ( opval == 0 or opval == 4 or opval == 5): part1s = string.split(flds[1],",") part2s = string.split(flds[2],",") part3s = string.split(flds[3],",") val1 = getVal(part1s[0]) val2 = getVal(part2s[0]) val3 = getVal(part3s[0]) if (opval == 0): val3 = val3 - (pReg+1) # print "part1 %d part2 %d val3:%d " % (val1, val2, val3) return_str = bin(opval,3) + bin(val1,3) + bin(val2,3) + bin(val3, 7) if opval == 3: part1s = string.split(flds[1],",") part2s = string.split(flds[2],",") val1 = getVal(part1s[0]) val2 = getVal(part2s[0]) # print "part1 %d part2 %d " % (val1, val2) return_str = bin(opval,3) + bin(val1,3) + '000' + bin(val2,7) elif (opval == 1 or opval ==2): part1s = string.split(flds[1],",") part2s = string.split(flds[2],",") part3s = string.split(flds[3],",") val1 = getVal(part1s[0]) val2 = getVal(part2s[0]) val3 = getVal(part3s[0]) # print "part1 %d part2 %d val3 %d" % (val1, val2, val3) # print "bin_op %s val1 %s val2 %s val3 %s" % (bin(opval,4), bin(val1,3), bin(val2,3), bin(val3,3)) return_str = bin(opval,3) + bin(val1,3) + bin(val2,3) + bin(val3,3) +'0000' elif (opval == 99): # .fill return_str = bin(int(flds[1]), 16) return return_str def pass2(program) : "translate assembly code and symbols to machine code" pReg=0 for lin in program: flds = string.split(lin) if codes.get(flds[0]) == None: flds = flds[1: ] #drop symbol if there is one # print "**start with symobl drop symbol %s " %(flds) # if lin[0] >' ' : flds = flds[1: ] # drop symbol if there is one # if not flds: print " ", lin, #print now if only a symbol # else : # try: instruction = assemble(flds, pReg) # print "====%03d %s: 0x%s %s" % (pReg, instruction, toHex(instruction), lin), print "0x%s " % (toHex(instruction)) pReg = pReg+1 # except: # print "***** ******** %s" % lin, def main () : program = sys.stdin.readlines() pass1 (program) pass2 (program) if __name__ == "__main__" : main()