#Chad Williamson #Two pass SIC/XE Assembler #SYMTAB is Dictionary, where key and address is symbol-value pair SYMTAB = {} #List of tuples OPTAB = [] #literal pool array LITPOOL = [] #input file inputFile = "literals_Formatted.txt" def main(): createOPTABLE() parseInputFile() def parseInputFile(): #data is the matrix containing all the instructions data = [] ins = open(inputFile, "r" ) #split into lines for line in ins: inputData = line.split() #remove all comments from program i = 0 j = len(inputData) for string in inputData: if "." in string: del inputData[i:j] i += 1 #check length of list. if one or two, then empty padding is added k = len(inputData) if k == 2: inputData = [""] + inputData if k == 1: inputData = [""] + inputData + [""] #add strings to instructions instructions = [str(n) for n in inputData] # this removes blank entries. add to matrix if instructions: data.append(instructions) #pass the matrix to be read in the first pass passOne(data) def createOPTABLE(): #mnemonic code, instruction length, hex value OPTAB.append(("ADD", "3", "18")) OPTAB.append(("ADDF", "3", "58")) OPTAB.append(("ADDR", "2", "90")) OPTAB.append(("AND", "3", "40")) OPTAB.append(("CLEAR", "2", "B4")) OPTAB.append(("COMP", "3", "28")) OPTAB.append(("COMPF", "3", "88")) OPTAB.append(("COMPR", "2", "A0")) OPTAB.append(("DIV", "3", "24")) OPTAB.append(("DIVF", "3", "64")) OPTAB.append(("DIVR", "2", "9C")) OPTAB.append(("FIX", "1", "C4")) OPTAB.append(("FLOAT", "1", "C0")) OPTAB.append(("HIO", "1", "F4")) OPTAB.append(("J", "3", "3C")) OPTAB.append(("JEQ", "3", "30")) OPTAB.append(("JGT", "3", "34")) OPTAB.append(("JLT", "3", "38")) OPTAB.append(("JSUB", "3", "48")) OPTAB.append(("LDA", "3", "00")) OPTAB.append(("LDB", "3", "68")) OPTAB.append(("LDCH", "3", "50")) OPTAB.append(("LDF", "3", "70")) OPTAB.append(("LDL", "3", "08")) OPTAB.append(("LDS", "3", "6C")) OPTAB.append(("LDT", "3", "74")) OPTAB.append(("LDX", "3", "04")) OPTAB.append(("LPS", "3", "D0")) OPTAB.append(("MUL", "3", "20")) OPTAB.append(("MULF", "3", "60")) OPTAB.append(("MULR", "2", "98")) OPTAB.append(("NORM", "1", "C8")) OPTAB.append(("OR", "3", "44")) OPTAB.append(("RD", "3", "D8")) OPTAB.append(("RMO", "2", "AC")) OPTAB.append(("RSUB", "3", "4C")) OPTAB.append(("SHIFTL", "2", "A4")) OPTAB.append(("SHIFTR", "2", "A8")) OPTAB.append(("SIO", "1", "F0")) OPTAB.append(("SSK", "3", "EC")) OPTAB.append(("STA", "3", "0C")) OPTAB.append(("STB", "3", "78")) OPTAB.append(("STCH", "3", "54")) OPTAB.append(("STF", "3", "80")) OPTAB.append(("STI", "3", "D4")) OPTAB.append(("STL", "3", "14")) OPTAB.append(("STS", "3", "7C")) OPTAB.append(("STSW", "3", "E8")) OPTAB.append(("STT", "3", "84")) OPTAB.append(("STX", "3", "10")) OPTAB.append(("SUB", "3", "1C")) OPTAB.append(("SUBF", "3", "5C")) OPTAB.append(("SUBR", "2", "94")) OPTAB.append(("SVC", "2", "B0")) OPTAB.append(("TD", "3", "E0")) OPTAB.append(("TIO", "1", "F8")) OPTAB.append(("TIX", "3", "2C")) OPTAB.append(("TIXR", "2", "B8")) OPTAB.append(("WD", "3", "DC")) #pass one of the assembler def passOne(data): #instructions are now in data matrix without comments and adjusted for space #access each instruction using data[n][m] #where n is the row of the instruction and m can be either 0 or 1 or 2 #when m = 0 is the label, m = 1 is the opcode, and m = 2 are the operand(s) numRows = len(data) z = 0 LOCCTR = 0 newData = data #errorFlag boolean for pass one. so far only set to 1 if invalid opcode is found errorFlag = False while z < numRows: #check if OPCODE is START if data[z][1] == "START": #add STARTs label to SYMTAB, if it exists if data[z][0] != "": if not (data[z][0] in SYMTAB): SYMTAB.update({data[z][0] : LOCCTR}) #Check if operand is not a blank space if data[z][2] != "": #Convert string to an int intNum = int(data[z][2]) #convert int to hexadecimal and remove 0x then set it to the starting address #startingAddress = hex(intNum) startingAddress = str(intNum) #local counter equal to starting address LOCCTR = startingAddress #newData is the data matrix but newData[3] will contain the calculated memory address of the instruction newData[z].append(LOCCTR) z += 1 else: #if the operand is a blank space set starting address and local counter to 0 startingAddress = hex(0) LOCCTR = startingAddress newData[z].append(LOCCTR) z += 1 if data[z][1] != "START": #loop for lines with opcode not equal to end while data[z][1] != "END": #appends LOCCTR using last value from while loop. this ensures the first instruction after START, starts at 0x0 newData[z].append(LOCCTR) #boolean which will be set to true if the OPCODE is valid, runs for each line opcodeFound = False #check label if data[z][0] != "": #this checks if dictionary is empty, if so add the first label, otherwise the next for loop will never be entered if not SYMTAB: SYMTAB.update({data[z][0]: LOCCTR}) for key in list(SYMTAB): #if the symbol is not in the SYMTAB then add it if not (data[z][0] in SYMTAB): SYMTAB.update({data[z][0]: LOCCTR}) #check OPTAB for opcode #if found for opcode in list(OPTAB): if data[z][1] == opcode[0]: opcodeFound = True #detect literals if (data[z][2] != ""): if ((data[z][2])[0] == "="): if data[z][2] not in LITPOOL: LITPOOL.append(data[z][2]) #updates LOCCTR by adding int value of LOCCTR and instruction length from opcode[1] LOCCTR = hex(int(LOCCTR, 16) + int(opcode[1])) #+OPCODE - SIC/XE format - 4 byte instruction if data[z][1] == str("+" + opcode[0]): #updates LOCCTR by adding int value of LOCCTR and instruction length from opcode[1] LOCCTR = hex(int(LOCCTR, 16) + int(opcode[1]) + 1) opcodeFound = True #other valid OPCODES if data[z][1] == "LTORG": opcodeFound = True data[z].append("") for literal in LITPOOL: literalOP = LITPOOL.pop(0) insertionList = ["*", literalOP, "", LOCCTR] SYMTAB.update({literalOP: LOCCTR}) if (literalOP[1]) == "X": LOCCTR = hex(int(LOCCTR, 16) + ((len(literalOP) - 4) / 2)) if (literalOP[1]) == "C": LOCCTR = hex(int(LOCCTR, 16) + (len(literalOP) - 4)) data.insert(z + 1, insertionList) z+=1 if data[z][1] == "EQU": opcodeFound = True data[z].append("") #insert label in symtab with value of the operand. if operand is * then value is address if (data[z][2] == "*"): SYMTAB.update({data[z][0]:LOCCTR}) try: int(data[z][2]) #operand is an integer, use it for the SYMTAB value SYMTAB.update({data[z][0]: data[z][2]}) except ValueError: #operand is not a * and is not an integer. check for math operations if (len(data[z][2]) > 1): if ("+" in data[z][2]): OPmath = data[z][2].split("+") SYMTAB.update({data[z][0]: (hex(int(SYMTAB.get(OPmath[0]),16) + int(SYMTAB.get(OPmath[1]),16)))}) elif ("-" in data[z][2]): OPmath = data[z][2].split("-") #update SYMTAB with data[z][0] with value of OPMATH[0] - OPMATH[1] SYMTAB.update({data[z][0]: (hex(int(SYMTAB.get(OPmath[0]),16) - int(SYMTAB.get(OPmath[1]),16)))}) elif ("*" in data[z][2]): OPmath = data[z][2].split("*") SYMTAB.update({data[z][0]: (hex(int(SYMTAB.get(OPmath[0]),16) * int(SYMTAB.get(OPmath[1]),16)))}) elif ("/" in data[z][2]): OPmath = data[z][2].split("/") SYMTAB.update({data[z][0]: (hex(int(SYMTAB.get(OPmath[0]),16) / int(SYMTAB.get(OPmath[1]),16)))}) #operand must be a word value: find the address and use it else: SYMTAB.update({data[z][0]: (hex(int(SYMTAB.get(data[z][2]),16)))}) if data[z][1] == "WORD": opcodeFound = True # add 3 (number of bytes in a word) to LOCCTR LOCCTR = hex(int(LOCCTR, 16) + 3) if data[z][1] == "RESW": opcodeFound = True LOCCTR = hex(int(LOCCTR, 16) + (3 * int(data[z][2]))) # add (3 * #operand) to LOCCTR if data[z][1] == "RESB": opcodeFound = True # add #operand to LOCCTR LOCCTR = hex(int(LOCCTR, 16) + int(data[z][2])) #append to make up for the fact no object code is generated for RESB data[z].append("") if data[z][1] == "BYTE": opcodeFound = True lengthOfConstant = len(data[z][2]) if (data[z][2])[:1] == "X": #hex constant. take length of string, strip the X and " and ", and divide by two since it is a hex constant lengthOfConstant = (lengthOfConstant - 3) / 2 if (data[z][2])[:1] == "C": #char constant. take length of string, strip the C and " and ", and that leaves number of bytes for char constant lengthOfConstant = lengthOfConstant - 3 #add length of constant to LOCCTR LOCCTR = hex(int(LOCCTR, 16) + int(lengthOfConstant)) if data[z][1] == "BASE": #BASE RELATIVE ADDRESSING opcodeFound = True #the boolean opcodeFound has not been set to true, must be an invalid opcode if not opcodeFound: errorFlag = True print("Invalid/unrecognized opcode: " + data[z][1] + " at line " + str(z)) z += 1 #process END statement if data[z][1] == "END": newData[z].append(LOCCTR) for literal in LITPOOL: literalOP = LITPOOL.pop(0) insertionList = ["*", literalOP, "", LOCCTR] SYMTAB.update({literalOP: LOCCTR}) if (literalOP[1]) == "X": LOCCTR = hex(int((len(literalOP) - 4) / 2)) if (literalOP[1]) == "C": LOCCTR = hex(int(LOCCTR, 16) + (len(literalOP) - 4)) data.insert(z + 1, insertionList) z+=1 z += 1 programLength = hex(int(LOCCTR, 16) - int(startingAddress, 16)) if errorFlag: print("Pass one has errors. Exiting") else: #pass to function to configure intermediate file passTwo(newData, programLength) # def writeIntermediateFile(newData): #the SYMTAB has all symbols and their addresses (no forward referencing though), and newData contains all lines and their respective addresses as well #create/overwrite existing intermediate file intermediate = open("intermediate.txt", "w") for instruction in newData: intermediate.write(instruction[3].upper() + "\t" + instruction[0].upper() + "\t" + instruction[1].upper() + "\t" + instruction[2].upper() + "\t\t" + instruction[4].upper() + "\n") print(instruction[3] + "\t" + instruction[0] + "\t" + instruction[1] + "\t" + instruction[2] + "\t\t" + instruction[4]) def passTwo(intrData, programLength): length = len(intrData) z = 0 baseAddress = "0x0" while z < length: #current instruction information currentLabel = intrData[z][0]; currentOPCODE = intrData[z][1]; currentOPERAND = intrData[z][2]; currentAddress = intrData[z][3]; currentInstLength = 0 for entry in OPTAB: if (entry[0] == currentOPCODE): currentInstLength = entry[1] elif (entry[0] == currentOPCODE[1:]): currentInstLength = str(int(entry[1]) + 1) target = 0; objCode = hex(0); addrOffset = hex(0) if (currentOPCODE == "START"): baseAddress = currentOPERAND intrData[z].append("") if (currentOPCODE == "BASE"): baseAddress = (SYMTAB.get(currentOPERAND)) intrData[z].append("") if intrData[z][1] == "WORD": #convert constant to object code objCode = hex(int(intrData[z][2])) objCode = objCode.split("x")[1] objCode = objCode.zfill(6) intrData[z].append(objCode) if intrData[z][1] == "BYTE": #convert constant to object code if (intrData[z][2])[:1] == "C": #translate characters to hex objCode = intrData[z][2][2:-1] newObjCode = "" for char in objCode: newObjCode += (format(ord(char), "x")) objCode = newObjCode if (intrData[z][2])[:1] == "X": #translate characters to hex objCode = intrData[z][2][2:-1] intrData[z].append(objCode) if (currentOPCODE == "RESW"): intrData[z].append("") if (currentOPCODE == "END"): intrData[z].append("") #make first decision based on operand #blank operand if currentOPERAND == "": for OPCODE in OPTAB: if currentOPCODE == OPCODE[0]: objCode = OPCODE[2].ljust(6, "0") objCode = "0x" + objCode objCode = hex(int(objCode,16) + 196608) objCode = objCode.split("x")[1] intrData[z].append(objCode) #for literal OPCODE if currentOPCODE in SYMTAB: if (currentOPCODE)[1:2] == "C": #translate characters to hex objCode = currentOPCODE[3:-1] newObjCode = "" for char in objCode: newObjCode += (format(ord(char), "x")) objCode = newObjCode if (currentOPCODE)[1:2] == "X": #translate characters to hex objCode = currentOPCODE[3:-1] intrData[z].append(objCode) #operand is a single register AXLBSTF if (len(currentOPERAND) == 1) and (currentOPERAND == "A" or currentOPERAND == "X" or currentOPERAND == "L" or currentOPERAND == "B" or currentOPERAND == "S" or currentOPERAND == "T" or currentOPERAND == "F"): for OPCODE in OPTAB: if currentOPCODE == OPCODE[0]: objCode = OPCODE[2] + registerEnum(currentOPERAND) + "0" intrData[z].append(objCode) #operand consists of two registers if (len(currentOPERAND) == 3): if "," in currentOPERAND: for OPCODE in OPTAB: if currentOPCODE == OPCODE[0]: objCode = OPCODE[2] + registerEnum(currentOPERAND[0]) + registerEnum(currentOPERAND[2]) intrData[z].append(objCode) #currentOPERAND starts with a # - immediate addressing if (currentOPERAND[:1] == "#"): #these are all immediate addressing modes. Split by extended format OPCODE or not if (currentOPCODE[:1] == "+"): #case 16: 010001: add OPCODE, bits, and 20 bits for hex conversion of value for OPCODE in OPTAB: if (currentOPCODE[1:] == OPCODE[0]): objCode = "0x" + OPCODE[2] + "000000" objCode = (hex(int(objCode,16) + 17825792)) # this value is equivalent to setting i and e bits to 1 try: int(currentOPERAND[1:]) objCode = int(objCode, 16) + (int(hex(int(currentOPERAND[1:])), 16)) except ValueError: objCode = int(objCode, 16) + (int(SYMTAB.get(currentOPERAND[1:]), 16)) objCode = hex(objCode).split("x")[1] intrData[z].append(objCode) else: #split this between constant, PC and BASE relative try: int(currentOPERAND[1:]) if (int(currentOPERAND[1:]) > -1) and (int(currentOPERAND[1:]) < 4096): #case 15: 010000 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 65536)) # this objCode = (hex(int(objCode,16) + int(hex(int(currentOPERAND[1:])), 16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: #case 17 and 18 for numbers/memory addresses requiring PC or BASE relative. for #230923 instructions if (int(currentOPERAND[1:]) < 2047) and (int(currentOPERAND[1:]) > -2048): #pc: case 17: 010010 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 73728)) objCode = (hex(int(objCode,16) + (int(currentOPERAND[1:], 16) - (int(currentAddress,16) + int(currentInstLength))))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: #base: case 18: 010100 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 81920)) objCode = (hex(int(objCode,16) + (int(currentOPERAND[1:],16) - int(baseAddress,16)))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) except ValueError: #for #LENGTH type instructions. first calculate offset offset = int(SYMTAB.get(currentOPERAND[1:]),16) - (int(currentAddress,16) + int(currentInstLength)) #VALUE PC ADDRESSING: CASE 17: 010010 if (offset < 2047) and (offset > -2048): for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 73728)) if (offset < 0): objCode = (hex(int(objCode,16) + (offset) + 4096)) else: objCode = (hex(int(objCode,16) + (offset))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 73728)) objCode = (hex(int(objCode,16) + (int(SYMTAB.get(currentOPERAND[1:]),16)) - int(baseAddress,16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) #currentOPERAND starts with a @ - indirect addressing if (currentOPERAND[:1] == "@"): if (currentOPCODE[:1] == "+"): #extended indirect addressing: CASE 12: 100001 for OPCODE in OPTAB: if (currentOPCODE[1:] == OPCODE[0]): objCode = "0x" + OPCODE[2] + "000000" objCode = (hex(int(objCode,16) + 34603008)) try: int(currentOPERAND[1:]) objCode = int(objCode, 16) + (int(currentOPERAND[1:], 16)) except ValueError: objCode = int(objCode, 16) + (int(SYMTAB.get(currentOPERAND[1:]), 16)) objCode = hex(objCode).split("x")[1] intrData[z].append(objCode) else: #not extended. split by constant, PC or BASE addressing: cases for 11, 13, 14 try: int(currentOPCODE[1:]) #case 11: 100000 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 131072)) objCode = (hex(int(objCode,16) + int(hex(int(currentOPERAND[1:])), 16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) except ValueError: #check for PC(CASE 13) and BASE: (CASE 14) #for @VALUE type instructions. first calculate offset offset = int(SYMTAB.get(currentOPERAND[1:]),16) - (int(currentAddress,16) + int(currentInstLength)) if (offset < 2047) and (offset > -2048): #PC RELATIVE INDIRECT: CASE 13 100010 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 139264)) if (offset < 0): objCode = (hex(int(objCode,16) + offset + 4096)) else: objCode = (hex(int(objCode,16) + offset)) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: #BASE RELATIVE INDIRECT: CASE 14 100100 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 147456)) objCode = (hex(int(objCode,16) + (int(SYMTAB.get(currentOPERAND[1:]),16)) - int(baseAddress,16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) #LITERALS if (currentOPERAND[:1] == "="): offset = (int(SYMTAB.get(currentOPERAND),16) - (int(currentAddress,16) + int(currentInstLength))) if (offset < 2047) and (offset > -2048): #PC: CASE 3 for LITERAL OPERAND for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 204800)) if (offset < 0): objCode = (hex(int(objCode,16) + offset + 4096)) else: objCode = (hex(int(objCode,16) + offset)) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: #BASE: CASE 4 for LITERAL OPERAND for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 212992)) objCode = (hex(int(objCode,16) + (int(SYMTAB.get(currentOPERAND),16)) - int(baseAddress,16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) #SIMPLE addressing type: currentOPERAND does not start with a # or @ or = if (int(currentInstLength) > 0) and (currentOPERAND[:1] != "=") and (currentOPERAND[:1] != "#") and (currentOPERAND[:1] != "@") and (currentOPERAND != "") and (len(currentOPERAND) > 1): #four categories of simple addressing: not index or extended, just index, just extended, both extended and index #category: not index and not extended if (currentOPCODE[:1] != "+") and ("," not in currentOPERAND): try: int(currentOPERAND,16) if (int(currentOPERAND,16) < 4096) and (int(currentOPERAND,16) > 0): #CASE 1 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 196608)) objCode = (hex(int(objCode,16) + int(hex(int(currentOPERAND)), 16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) except ValueError: #calculate offset, find if PC or BASE offset = int(SYMTAB.get(currentOPERAND),16) - (int(currentAddress,16) + int(currentInstLength)) if (offset < 2047) and (offset > -2048): #PC: CASE 3 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 204800)) if (offset < 0): objCode = (hex(int(objCode,16) + offset + 4096)) else: objCode = (hex(int(objCode,16) + offset)) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: #BASE: CASE 4 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 212992)) objCode = (hex(int(objCode,16) + (int(SYMTAB.get(currentOPERAND),16)) - int(baseAddress,16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) #category: not index but IS extended if (currentOPCODE[:1] == "+") and ("," not in currentOPERAND): for OPCODE in OPTAB: if (currentOPCODE[1:] == OPCODE[0]): objCode = "0x" + OPCODE[2] + "000000" objCode = (hex(int(objCode,16) + 51380224)) try: int(currentOPERAND) objCode = int(objCode, 16) + (int(currentOPERAND, 16)) except ValueError: objCode = int(objCode, 16) + (int(SYMTAB.get(currentOPERAND),16)) objCode = hex(objCode).split("x")[1] intrData[z].append(objCode) #category: IS index, but not extended if (currentOPCODE[:1] != "+") and ("," in currentOPERAND) and (len(currentOPERAND) > 3): #CASE: 5, 7, 8 try: int(currentOPERAND[:-2],16) if (int(currentOPERAND[:-2],16) < 4096) and (int(currentOPERAND[:-2],16) > 0): #CASE 5 for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 229376)) objCode = (hex(int(objCode,16) + int(hex(int(currentOPERAND[:-2])), 16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) except ValueError: #calculate offset, find if PC or BASE offset = int(SYMTAB.get(currentOPERAND[:-2]),16) - (int(currentAddress,16) + int(currentInstLength)) if (offset < 2047) and (offset > -2048): for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 237568)) if (offset < 0): objCode = (hex(int(objCode,16) + offset + 4096)) else: objCode = (hex(int(objCode,16) + offset)) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) else: for OPCODE in OPTAB: if (currentOPCODE == OPCODE[0]): objCode = "0x" + OPCODE[2] + "0000" objCode = (hex(int(objCode,16) + 245760)) objCode = (hex(int(objCode,16) + (int(SYMTAB.get(currentOPERAND[:-2]),16)) - int(baseAddress,16))) objCode = objCode.split("x")[1].zfill(6) intrData[z].append(objCode) #category: both index and extended if (currentOPCODE[:1] == "+") and ("," in currentOPERAND) and (len(currentOPERAND) > 3): for OPCODE in OPTAB: if (currentOPCODE[1:] == OPCODE[0]): objCode = "0x" + OPCODE[2] + "000000" objCode = (hex(int(objCode,16) + 59768832)) try: int(currentOPERAND[:-2],16) objCode = int(objCode, 16) + (int(currentOPERAND[:-2], 16)) except ValueError: objCode = int(objCode, 16) + (int(SYMTAB.get(currentOPERAND[:-2]),16)) objCode = hex(objCode).split("x")[1] intrData[z].append(objCode) z+= 1 #END OF WHILE LOOP #pass to intermediate function just to print, intermediate function not really needed writeIntermediateFile(intrData) #write object code! object = open("object.txt", "w") #write header line object.write("H^") lineLength = 0 textLine = "" comLength = len(intrData) y = 0 firstAddress = "" while y < comLength: #write header if intrData[y][1] == "START": object.write(intrData[y][0] + "^" + intrData[y][2].zfill(6) + "^" + (programLength.split("x")[1].zfill(6)).upper() + "\n") #write text lines if (intrData[y][4] != "START") & (intrData[y][4] != "END"): if (intrData[y][4] == "") & (textLine != ""): object.write("T^" + firstAddress.zfill(6)+ "^" + ((hex(int(lineLength/2)).split("x")[1]).zfill(2)).upper() + "^" + (textLine[:-1]).upper() + "\n") textLine = "" lineLength = 0 firstAddress = "" if (intrData[y][4] != ""): if lineLength + len(intrData[y][4]) <= 60: textLine += intrData[y][4] + "^" lineLength += len(intrData[y][4]) if firstAddress == "": if "x" in intrData[y][3]: firstAddress = intrData[y][3].split("x")[1] else: firstAddress = intrData[y][3] else: object.write("T^" + firstAddress.zfill(6) + "^" + ((hex(int(lineLength/2)).split("x")[1]).zfill(2)).upper() + "^" + (textLine[:-1]).upper() + "\n") textLine = intrData[y][4] + "^" lineLength = len(intrData[y][4]) if "x" in intrData[y][3]: firstAddress = intrData[y][3].split("x")[1] else: firstAddress = intrData[y][3] if intrData[y][1] == "END": if "x" in intrData[0][2]: object.write("E^" + ((intrData[0][2].split("x")[1]).zfill(6)).upper() + "\n") else: object.write("E^" + ((intrData[0][2]).zfill(6)).upper() + "\n") y += 1 def registerEnum(char): if char == "A": return "0" if char == "X": return "1" if char == "L": return "2" if char == "B": return "3" if char == "S": return "4" if char == "T": return "5" if char == "F": return "6" main()