import asm def padBin(number,bit=8): return asm.padBin(asm.toBin(number),bit=bit) def toDec(binNumber): return asm.toDec(binNumber) doc = """ 0000 NOP 0001 LDA memory > A 0010 ADD A + memspace 0011 SUB A - memspace 0100 STA A > memory 0101 OUT A > OUT 0110 JMP Jump to adress 0111 LDI par > A 1000 JIF Jump if greater 1001 JIE Jump if equal 1010 LDP memory[A] > A 1011 INP IN > A 1100 JMA Jump to A 1101 --- not implemented 1110 STP memory[par] > memory[A] 1111 HLT Halt """ def compile(cmd,par,memAddr): # Every function creates unknown vars, even if it makes no sense in it case, # because if the function sits inside a user-defined function vars may be # defined later #try: if cmd=="newVar": # creates new var and allocates memory-adress for it print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 print("[i] newVar is obsolete in this version of tronScript") elif cmd=="newArray": # creates new array and allocates memory-adress for it print("Creating array '"+par[0].upper()+"' at memory-space "+padBin(len(varRec)+(2**8)/2)+" - "+padBin(len(varRec)+int(par[1])+(2**8)/2)) for i in range(int(par[1])): varRec["array_"+par[0].upper()+"["+i+"]"] = len(varRec)+(2**8)/2 elif cmd=="jumpMark": # creates a jumpMark and saves current adress in the DB for later use by the jump-name-replacement print("Creating jumpMark '"+par[0].upper()+"' at memory-address "+padBin(memAddr)) jumpMark[par[0].upper()] = memAddr elif cmd=="jump": # creates dummy jump code for later replacement # we have to do it this way, beacause a jumpMark may be defined after the jump-call return [ # will be replaced after script-compilation "Jump_"+par[0].upper() ] elif cmd=="getVarAddress": # stores the memory-adress of a var into another # maybe needed, if user want to access vars with # custom asssembly code try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[1].upper()] except: print("Creating var '"+par[1].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[1].upper()] = len(varRec)+(2**8)/2 return [ ## load the Var-Adress into A Register and save it into specified var # LDI toDec("0111"+padBin(varRec[par[0].upper()])), # STA variable to store the current pointer in toDec("0100"+padBin(varRec[par[1].upper()])), ] elif cmd=="getArrayAddress": # like getVarAdress, but for arrays # arrayName Index storeVar try: t = varRec["array_"+par[0].upper()+"["+par[1]+"]"] except: print("Undefined Array") exit() try: _ = int(par[1]) except: print("Expected array-index (integer)") exit() return [ ## load the Var-Adress into A Register and save it into specified var # LDI toDec("0111"+padBin(varRec["array_"+par[0].upper()+"["+par[1]+"]"])), # STA variable to store the current pointer in toDec("0100"+padBin(varRec[par[2].upper()])), ] elif cmd=="exec": # execute a user defined function try: t = varRec[par[0].upper()] except: print("Creating function-jumpback-var '"+par[0].upper()+"_JUMPBACK' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()+"_JUMPBACK"] = len(varRec)+(2**8)/2 return [ ## remember current pointer, so you can jump back here after function execution is done # LDI toDec("0111"+padBin(pointer)), # STA variable to store the current pointer in toDec("0100"+padBin(varRec[par[0].upper()+"_JUMPBACK"])), # will be replaced after script-compilation "Exec_"+par[0].upper()# jumpback function-call-var ] elif cmd=="setVar": # gives a var a defined value try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 if par[1][0]=="b": par[1] = toDec(par[1][1:]) return [ ## loads desired value into the A register and then stores it at the variables memory adress # LDI value toDec("0111" + padBin(int(par[1]))), # STA var Name toDec("0100" + padBin(varRec[par[0].upper()])) ] elif cmd=="copyVar": # gives a var the value of another var try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[1].upper()] except: print("Creating var '"+par[1].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[1].upper()] = len(varRec)+(2**8)/2 return [ ## load memory-space of var 1 into register A and the store it into memory-space of var 2 # LDA var 1 toDec("0001" + padBin(varRec[par[0].upper()])), # STA var 2 toDec("0100" + padBin(varRec[par[1].upper()])) ] elif cmd=="setArrayIndex": # defines the value of an array (par0) index (par1) to be (par2) try: t = varRec["array_"+par[0].upper()+"["+par[1]+"]"] except: print("Undefined array") exit() try: _=int(par[1]) except: print("Expected array-index (integer)") exit() if par[2][0]=="b": par[2] = toDec(par[2][1:]) return [ ## loads desired value into the A register and then stores it at the variables memory adress # LDI value toDec("0111" + padBin(int(par[2]))), # STA var Name toDec("0100" + padBin(varRec["array_"+par[0].upper()+"["+par[1]+"]"])) ] elif cmd=="getArrayIndex": # puts the value of an array (par0) index (par1) into var (par2) try: t = varRec["array_"+par[0].upper()+"["+par[1]+"]"] except: print("Undefined Array") exit() try: t = varRec[par[2].upper()] except: print("Creating var '"+par[2].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[2].upper()] = len(varRec)+(2**8)/2 try: _=int(par[1]) except: print("Expected array-index (integer)") exit() return [ ## load memory-space of var 1 into register A and the store it into memory-space of var 2 # LDA var 1 toDec("0001" + padBin(varRec["array_"+par[0].upper()+"["+par[1]+"]"])), # STA var 2 toDec("0100" + padBin(varRec[par[2].upper()])) ] elif cmd=="write": # writes to the console try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 return [ ## load the variable into register A, then print it # LDA var Name toDec("0001" + padBin(varRec[par[0].upper()])), # OUT null toDec("0101" + "00000000") ] elif cmd=="read": # reads from the console try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 return [ ## input > register A; register A > var # INP null toDec("1011" + "00000000"), # STA var Name toDec("0100" + padBin(varRec[par[0].upper()])) ] elif cmd=="add": # adds to numbers and stores the answer in another try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[1].upper()] except: print("Creating var '"+par[1].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[1].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[2].upper()] except: print("Creating var '"+par[2].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[2].upper()] = len(varRec)+(2**8)/2 return [ ## load var 1 into register A; add var 2, store in var 3 # LDA var Name in1 toDec("0001" + padBin(varRec[par[0].upper()])), # ADD var Name in2 toDec("0010" + padBin(varRec[par[1].upper()])), # STA var Name out toDec("0100" + padBin(varRec[par[2].upper()])) ] elif cmd=="subtract": # in1 - in2 = out try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[1].upper()] except: print("Creating var '"+par[1].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[1].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[2].upper()] except: print("Creating var '"+par[2].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[2].upper()] = len(varRec)+(2**8)/2 return [ ## laod var 1 into register A; subtract var 2; store in var 3 # LDA var Name in1 toDec("0001" + padBin(varRec[par[0]])), # SUB var Name in2 toDec("0011" + padBin(varRec[par[1]])), # STA var Name out toDec("0100" + padBin(varRec[par[2]])) ] elif cmd=="if": # if clause #cmd p0 p1 p2 p3 p4: #if VAR ?? VAR cmd pars try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[2].upper()] except: print("Creating var '"+par[2].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[2].upper()] = len(varRec)+(2**8)/2 comp1=par[0].upper() comp2=par[2].upper() comp=par[1] shellcode=compile(par[3],par[4:],memAddr+4) if not shellcode: return ["Error","I had problems getting the internal shellcode. Sorry :("] if shellcode[0]=="Error": return ["Error","Internal shellcode compilation thew an Error:\n"+shellcode[1]] ## binary code that magicaly works: if comp=="==": ret = [ # LDI konst toDec("0111" + "10000000"), # STA temp toDec("0100" + "11111111"), # LDA comp1 toDec("0001" + padBin(varRec[comp1])), # ADD konst toDec("0010" + "11111111"), # SUB comp2 toDec("0011" + padBin(varRec[comp2])), # JIE toDec("1001" + padBin(memAddr+7)), # JMP toDec("0110" + padBin(memAddr+7+len(shellcode))) ] elif comp=="!=": ret = [ # LDI konst toDec("0111" + "10000000"), # STA temp toDec("0100" + "11111111"), # LDA comp1 toDec("0001" + padBin(varRec[comp1])), # ADD konst toDec("0010" + "11111111"), # SUB comp2 toDec("0011" + padBin(varRec[comp2])), # JIE toDec("1001" + padBin(memAddr+6+len(shellcode))) ] elif comp==">=": ret = [ # LDI konst toDec("0111" + "10000000"), # STA temp toDec("0100" + "11111111"), # LDA comp1 toDec("0001" + padBin(varRec[comp1])), # ADD konst toDec("0010" + "11111111"), # SUB comp2 toDec("0011" + padBin(varRec[comp2])), # JIF toDec("1000" + padBin(memAddr+6+len(shellcode))) ] elif comp==">": ret = [ # LDI konst toDec("0111" + "01111111"), # STA temp toDec("0100" + "11111111"), # LDA comp1 toDec("0001" + padBin(varRec[comp1])), # ADD konst toDec("0010" + "11111111"), # SUB comp2 toDec("0011" + padBin(varRec[comp2])), # JIF toDec("1000" + padBin(memAddr+6+len(shellcode))) ] elif comp=="<=": ret = [ # LDI konst toDec("0111" + "10000000"), # STA temp toDec("0100" + "11111111"), # LDA comp2 toDec("0001" + padBin(varRec[comp2])), # ADD konst toDec("0010" + "11111111"), # SUB comp1 toDec("0011" + padBin(varRec[comp1])), # JIF toDec("1000" + padBin(memAddr+6+len(shellcode))) ] elif comp=="<": ret = [ # LDI konst toDec("0111" + "01111111"), # STA temp toDec("0100" + "11111111"), # LDA comp2 toDec("0001" + padBin(varRec[comp2])), # ADD konst toDec("0010" + "11111111"), # SUB comp1 toDec("0011" + padBin(varRec[comp1])), # JIF toDec("1000" + padBin(memAddr+6+len(shellcode))) ] for s in shellcode: ret.append(s) return ret elif cmd=="for": # for loop: "for [goal] [counter] [step] [cmd] [pars]" # == for [counter] in range(0,[goal],[step]): # [cmd]([pars]) try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[1].upper()] except: print("Creating var '"+par[1].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[1].upper()] = len(varRec)+(2**8)/2 try: t = varRec[par[2].upper()] except: print("Creating var '"+par[2].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[2].upper()] = len(varRec)+(2**8)/2 goal = par[0].upper() clock = par[1].upper() step = par[2].upper() shellcode=compile(par[3],par[4:],memAddr+12) ret = [ # LDI konst toDec("0111" + "00000000"), # STA temp toDec("0100" + padBin(varRec[clock])), # LDI konst <-- jump back to toDec("0111" + "10000000"), # STA temp toDec("0100" + "11111111"), # LDA clock toDec("0001" + padBin(varRec[clock])), # ADD konst toDec("0010" + "11111111"), # SUB goal toDec("0011" + padBin(varRec[goal])), # JIE toDec("1001" + padBin(memAddr+12+len(shellcode)+1)), # LDA clock toDec("0001" + padBin(varRec[goal])), # ADD step toDec("0010" + padBin(varRec[step])), # STA clock toDec("0100" + padBin(varRec[goal])) ] for s in shellcode: ret.append(s) # JMP ret.append(toDec("0110" + padBin(memAddr+2))) return ret elif cmd=="asm" or cmd[0]==":": # compiles assembler to machine-code if cmd=="asm": opcode = par[0] param = par[1] else: opcode = cmd[1:] param = par[0] if param[:2]=="b#": param = toDec(param[2:]) elif param[:2]=="d#": param = param[2:] elif param[:2]=="v#": try: t = varRec[param[2:].upper()] except: print("Creating var '"+param[2:].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[param[2:].upper()] = len(varRec)+(2**8)/2 param = varRec[param[2:].upper()] elif param in ["-","none"]: param = toDec("00000000") elif param in ["~","all"]: param = toDec("11111111") else: return ["Error","Invalid param supplied to asm-command (no valid prefix found)"] for a in range(len(asm.asmMap)): if asm.asmMap[a]==opcode: print("Found matching opcode") return [toDec(padBin(a,bit=4)+padBin(param))] elif cmd=="shellcode": # insertes raw shellcode into the programm return [toDec("".join(par))] elif cmd=="push": try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 ret = [ ### value to temp # LDA value toDec("0001" + padBin(varRec[par[0]])), # STA temp toDec("0100" + padBin(varRec["temp"])), ### increment stackpointer # LDI konst toDec("0111" + "00000001"), # we are going to use a overflow to subtract (2's-complement) # ADD stack_pointer toDec("0010" + padBin(varRec["stack_pointer"])), # STA stack_pointer toDec("0100" + padBin(varRec["stack_pointer"])), ### A > write as new element # STP temp toDec("1110" + padBin(varRec["temp"])) ] return ret elif cmd=="pop": try: t = varRec[par[0].upper()] except: print("Creating var '"+par[0].upper()+"' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[par[0].upper()] = len(varRec)+(2**8)/2 ret = [ ### read the last element > A # LDI stack-base toDec("0111" + "11111111"), # SUB stack_pointer toDec("0011" + padBin(varRec["stack_pointer"])), # LDP konst toDec("1010" + "00000000"), # STA stack_pointer toDec("0100" + padBin(varRec[par[0]])), ### decrement stackpointer # LDI konst toDec("0111" + "11111111"), # we are going to use a overflow to subtract (2's-complement) # ADD stack_pointer toDec("0010" + padBin(varRec["stack_pointer"])), # STA stack_pointer toDec("0100" + padBin(varRec["stack_pointer"])) ] return ret elif cmd=="nop": # nothing... return [toDec("0000" + "00000000")] elif cmd=="halt": # halts execution of programm return [toDec("1111" + "11111111")] else: return ["Error","Unimplemented Function: "+str(cmd)] #except Exception as e: # return ["Error","Unknown Error: "+str(e)] bits = 12 varRec = {"temp": (2**8)/2, "stack_pointer": (2**8)/2 + 1 } # to store VarName -> memory-address jumpMark = {} # to store jumpMarkName -> jump-address if __name__ == "__main__": print("[tronScript-Compiler by CyberCodeDragon]") print("! Unstable Beta-Version with stack") memory = [] for i in range(2**bits): #expand memory memory.append(0) pointer = 0 funcTable = [] # [[funcName,funcCode],...] for f in asm.os.listdir("tronScript"): #display all found scripts if f[-5:]==".tron": print("> "+"tronScript/"+f) filePath = raw_input("file to compile> ") inFile = filePath.split("\\") inFile = inFile[len(inFile)-1] tmp = inFile.split(".") ext = tmp[len(tmp)-1] name = inFile.split("."+ext)[0] print("[*] Reading "+inFile) with open(filePath) as f: code = f.read().replace(" ","") #read file and remove tabs c = code.split("\n") #c = lines of code #detect functions for l in range(len(c)): #for every line of code elems = c[l].split(" ") #elems = [cmd,pa1,par2,...,parN] if elems[0]=="function": funcName = elems[1] funcCode = code.split("function "+funcName+" {")[1].split("}")[0].split("\n") #get the function Code funcName = funcName.upper() print("detected function '"+funcName+"' in line "+str(l)+":\n"+"\n".join(funcCode)) for i in range(len(funcCode)+0): c[l+i]="#function-code" #replace function with a comment -> dont mess up later parsing funcTable.append([funcName,funcCode]) try: #create jumpback-var if not existing (does probably not exist) t = varRec[funcName+"_JUMPBACK"] except: print("Creating function-jumpback-var '"+funcName+"_JUMPBACK' at memory-address "+padBin(len(varRec)+(2**8)/2)) varRec[funcName+"_JUMPBACK"] = len(varRec)+(2**8)/2 #parse code for l in range(len(c)): #for every line in code if c[l] not in ["","\n"]: #if lines is not empty print("Parsing line "+str(l)+": "+c[l]) cmd = c[l].split(" ")[0] if not cmd[0]=="#": #dont parse comments if cmd in ["halt","nop"]: #cmds without params par = [] else: par = c[l].split(cmd+" ")[1].split(" ") r = compile(cmd,par,pointer) #compile if r: if r[0]=="Error": #print error print("Error compiling line "+str(l)+" {"+c[l]+"}: \n"+str(r[1])) exit() for ret in r: veryVerbose = False if veryVerbose: try: print("Compiled to: "+padBin(ret,bit=12)) except: print("Compiled to: "+str(ret)) memory[pointer] = ret #write code to memory pointer+=1 try: if padBin(memory[pointer-1],bit=12)[:4]!="1111": #if the last command is not a HLT command print("Appending HLT-Command") # HLT memory[pointer] = toDec("1111"+"11111111") print("HLT at "+padBin(pointer)+": "+padBin(memory[pointer],bit=12)) pointer+=1 except: #looks like the last command was a placeholder: not a HLT command print("Appending HLT-Command") # HLT memory[pointer] = toDec("1111"+"11111111") print("HLT at "+padBin(pointer)+": "+padBin(memory[pointer],bit=12)) pointer+=1 #replace jump-names for m in range(len(memory)): try: if memory[m][:5]=="Jump_": #if at memory-adress is just a jump-dummy print("Inserting Jump-Adress at "+padBin(m,bit=12)) memory[m]=toDec("0110"+padBin(jumpMark[memory[m][5:]])) #replace with real jump adress except: t=1 #append function-shellcode funcMapper = {} #map funcName to funcCode for f in range(len(funcTable)): print("Appending shellcode for function "+str(funcTable[f][0])+" at adress "+padBin(pointer)) funcMapper[funcTable[f][0]] = pointer #remember where you put dat function for l in range(len(funcTable[f][1])): if funcTable[f][1][l] not in ["","halt","nop"]: ret=compile(funcTable[f][1][l].split(" ")[0],funcTable[f][1][l].split(" ")[1:],pointer) try: if ret[0]=="Error": print("An Error occured, when compiling function shellcode for function '"+funcTable[f][0]+"':\n"+str(e)) else: for r in range(len(ret)): memory[pointer]=ret[r] #append compiled function memory pointer+=1 except: t=1 ## jump back after function execution # LDI konst=3 memory[pointer] = toDec("0111" + "00000011") pointer+=1 # ADD jumpBackVar memory[pointer] = toDec("0010" + padBin(varRec[funcTable[f][0]+"_JUMPBACK"])) pointer+=1 # JMA null memory[pointer] = toDec("1100" + "00000000") pointer+=1 print("FuncMapper: "+str(funcMapper)) print("Var Assignment:") varAss = str(varRec)[1:][:-1].split(", ") print("#VAR-NAME# #ADDRESS#") for va in range(len(varAss)): #print all vars with their memory-location print(varAss[va].split("'")[1]+": "+" "*(12-len(varAss[va].split("'")[1]))+padBin(int(varAss[va].split("': ")[1]))) #replace func-names for m in range(len(memory)): try: if memory[m][:5]=="Exec_": #if there is just a function-call-dummy print("Inserting Exec-Call-Adress at "+padBin(m,bit=12)) memory[m]=toDec("0110"+padBin(funcMapper[memory[m][5:]])) #replace it with a jump to the function except Exception as e: if str(e) != "'int' object has no attribute '__getitem__'": print "Error while replacing func-name: "+str(e)+"\n (I don't know why, sorry)" try: print("Removing old "+name+".asmTron") os.remove(name+".asmTron") except: t=1 print("Saving as "+name+".asmTron") with open(name+".asmTron", 'wb') as f: t=asm.pickle.dumps([12,memory]) t=asm.zlib.compress(t) f.write(t) print("Done.")