def main(): lexout = True #asmout = False options = "" filearg = "" # print information if there are no arguments if len(sys.argv) == 1: print("%sProvide a file.\n" % cBR) information() # get arguments else: for arg in sys.argv: if re.match(r"-", arg): options = arg else: filearg = arg # "parse" options if re.search(r"h", options): information() if re.search(r"l", options): lexout = True #if re.search(r"a", options): # asmout = True if filearg == "": information() # open try: print("%sOpening %s[%s]" % (cBW, cW, sys.argv[1])) with open(sys.argv[1], "r") as f: print("\t.") file = f.read() except FileNotFoundError: print("%s\tERROR %sfile not found.%s" % (cBR, cR, cW)) exit() # lex types = [] values = [] lines = [] print("%sLexing%s" % (cBW, cW)) types, values, lines = lexfile(file, lexout) # assemble print("%sAssembling%s" % (cBW, cW)) assemble(types, values, lines)
def t_asm(ass, ex, exact=True, check_dis=True): ass = ass.strip() bc = asm.assemble(ass) dis = disasm.disassemble(bc) dis = unformat(dis) if check_dis and dis != ass: print(ass) print(dis) assert (dis == ass) fname = "tmp.tpc" system_rm(fname) system_rm(TMP) save(fname, bc) cmd = VM + fname + " > " + TMP system(cmd) res = load("tmp.txt").strip() if exact: if ex != res: print(ass) print(ex) print(res) assert (ex == res) else: if ex not in res: print(ass) print(ex) print(res) assert (ex in res)
def t_asm(ass, ex, exact=True,check_dis=True): ass = ass.strip() bc = asm.assemble(ass) dis = disasm.disassemble(bc) dis = unformat(dis) if check_dis and dis != ass: print (ass) print (dis) assert(dis == ass) fname = "tmp.tpc" system_rm(fname) system_rm(TMP) save(fname,bc) cmd = VM + fname + " > " + TMP system(cmd) res = load("tmp.txt").strip() if exact: if ex != res: print (ass) print (ex) print (res) assert(ex == res) else: if ex not in res: print (ass) print (ex) print (res) assert(ex in res)
def test_data_instructions(self): prefix = 'data' files = list(glob.glob('asm/{}*.asm'.format(prefix))) self.assertNotEqual(files, []) for fname in files: with self.subTest(file=fname): with open(fname, 'r') as f: code = asm.assemble(f) with open(fname[:-3] + 'hex', 'r') as outf: code_hex = [] for line in outf: code_hex.extend(line.strip().split(' ')) for i, b in enumerate(code): self.assertEqual(b, int(code_hex[i], 16)) print('{} OK'.format(fname))
continue # Split to words infile[x] = infile[x].split() # Handle Label if infile[x][0][-1] == ":": labels[infile[x][0][:-1]] = count infile[x].pop(0) # If left with an empty string after removal, pop it and come again, else increase count because you have a valid line if len(infile[x]) == 0: infile.pop(x) continue count += 1 x += 1 x = 0 # Civilize the instr, remove labelish anarchy while x < len(infile): if (infile[x][-1][0] != 'R' or not infile[x][-1][1].isdigit()) and infile[x][-1][0] != '#': infile[x][-1] = "#" + str(labels[infile[x][-1]] - 1) infile[x] = " ".join(infile[x]) # Translate the string to machine code infile[x] = asm.assemble(infile[x]) + ";" x += 1 count = 0 for x in infile: num = hex(count)[2:].upper() print 'i' + (2 - len(num)) * '0' + num + " = " + x count += 1
def fastcall(addr, ret_t, *arg_ts): """In-process functions with MS __fastcall calling convention. First two arguments passed in ECX and EDX, left-to-right. The rest are pushed on stack right-to-left. Callee cleans up stack. Return in EAX. (EAX,ECX,EDX are thus available for use.) """ # assemble an asm wrapper around the function # this gets done just once, at module load time, by the decorator # # since parameters are unknown, the machine code is parametrized via # string.format(*args), to be swapped in on function call # # alternatively, could wrap with an stdcall... but eh, this is more flexible s = 'push ebx;' junk = 0 # how many bytes to clean off the stack # first two arguments in registers if len(arg_ts)>0: s += 'mov ecx {0};' if len(arg_ts)>1: s += 'mov edx {1};' # variable arguments on the stack vargs = len(arg_ts)-2 if vargs>0: junk += 4*vargs # args are DWORDs for n in range(2, 2+vargs): s += 'mov eax {%d}; push eax;' % (n,) # function call and cleanup s +=''' mov ebx $func_addr call ebx pop ebx retn $stack_junk ''' asm_code = s machine_code = asm.assemble(asm_code, func_addr=asm.DWORD(addr), stack_junk=asm.WORD(junk)) def cfun(*args): # pack arguments into 4-byte form suitable for stack # TODO sign? # TODO proper handling of arg_ts ctypes conv_args = () for arg in args: conv_args+=(asm.DWORD(arg),) args = conv_args # insert particular arguments into preassembled machine code code = machine_code.format(*args) # execute ret = c_uint(asm.call(code)()) # hammer the retval into a correct shape via pointer typecast return cast(pointer(ret), POINTER(ret_t)).contents def wrap1(f): # this part is just like it was for stdcall and cdecl def wrap2(*args): gen = f(*args) args = gen.send(None) # let coroutine work with args if it wants to ret = cfun(*args) # execute C function, hope it doesn't failboat ret = gen.send(ret) # let coroutine work with retval if it wants to return ret return wrap2 return wrap1
def assemble_input(self, *args): assembly = self.text_box.get(0.0, END) program = assemble(assembly) with tempfile.TemporaryFile() as f: f.write(program)
def test_assemble_example(): with open('example.s') as f: example = f.read() assert assemble(example) == prog
def test_assemble_disasseble_cycle(): code = assemble(asm) assert assemble(disassemble(code)) == code
def test_assemble_disassembled(): assert assemble(asm) == prog