class Context(object): def __init__(self, instructions): self.registers = Registers() self.flags = Flags() self.instructions = instructions self.heap = Memory(size=40, mode=HEAP, start_address=0x0000) self.stack = Memory(size=40, mode=STACK, start_address=0xFFFF) self.registers.set(SP, 0xFFFF) def run(self): """ initialize the context and execute the first instruction """ self.registers.reset() def step(self): """ execute the next instruction whose address in the EIP value :return: """ self.registers.tick() self.flags.tick() self.heap.tick() self.stack.tick() next_address = self.registers.get(IP).value if next_address < len(self.instructions): next_instruction = self.instructions[next_address] next_instruction.execute(self) self.registers.set(IP, next_address + 1) return True else: return False
class Interp: def __init__(self): self.cmds = { 'ADD': self.add, 'ADDU': self.add, 'SUB': self.add, 'SUBU': self.add, 'OR': self.add, 'AND': self.add, 'NOR': self.add, 'XOR': self.add, 'ADDI': self.addi, 'ADDIU': self.addi, 'SUBI': self.addi, 'SUBIU': self.addi, 'ANDI': self.addi, 'ORI': self.addi, 'XORI': self.addi, 'LI': self.li, 'MOVE': self.move, 'SLT': self.slt, 'SLTU': self.slt, 'SLTI': self.slti, 'SLTIU': self.slti, 'SLL': self.sll, 'SRL': self.sll, 'J': self.j, 'JAL': self.jal, 'JR': self.jr, 'BEQ': self.beq, 'BNE': self.beq, 'MULT': self.mult, 'MULTU': self.mult, 'DIV': self.div, 'DIVU': self.div, 'MFLO': self.mfhi, 'MFHI': self.mfhi, 'NOP': self.nop, 'PYEVAL': self.pyeval, 'PYJAL': self.pycall, 'SYSCALL': self.pysyscall, 'PYEXEC': self.pyexec, 'LW': self.lw, 'SW': self.lw, } self.regs = Registers() self.mem = Memory(32) def pcinc(self): pc = self.regs.get('pc') pc += 4 self.regs.set('pc', pc, special=True) def add(self, name, d, s, t): sval = self.regs.get(s) tval = self.regs.get(t) if name == 'SUB' or name == 'SUBU': sval -= tval elif name == 'OR': sval |= tval elif name == 'AND': sval &= tval elif name == 'XOR': sval ^= tval elif name == 'NOR': sval = ~(sval | tval) else: sval += tval if name == 'ADDU' or name == 'SUBU': sval = abs(sval) self.regs.set(d, sval) self.pcinc() def addi(self, name, d, s, i): val = self.regs.get(s) if name == 'SUBI' or name == 'SUBIU': val -= i elif name == 'ADDI' or name == 'ADDIU': val += i elif name == 'ANDI': val &= i elif name == 'ORI': val |= i elif name == 'XORI': val ^= i if name == 'ADDIU' or name == 'SUBIU': val = abs(val) self.regs.set(d, val) self.pcinc() def li(self, name, d, i): self.addi('ADDI', d, '$0', i) def move(self, name, d, s): self.add('ADD', d, s, '$0') def slt(self, name, d, a, b): aval = self.regs.get(a) bval = self.regs.get(b) if name == 'SLTU': aval = abs(aval) bval = abs(bval) if aval < bval: val = 1 else: val = 0 self.regs.set(d, val) self.pcinc() def slti(self, name, d, a, imm): aval = self.regs.get(a) self.regs.set(d, int(aval < imm)) self.pcinc() def sll(self, name, d, s, i): val = self.regs.get(s) if i > 5: i = 5 if name == 'SLL': val <<= i elif name == 'SRL': val >>= i self.regs.set(d, val) self.pcinc() def j(self, name, addr): self.regs.set('pc', addr, special=True) def jr(self, name, r): self.regs.set('pc', self.regs.get(r), special=True) def jal(self, name, addr): self.regs.set('$ra', self.regs.get('pc') + 4) self.j('J', addr) def beq(self, name, a, b, addr): aval = self.regs.get(a) bval = self.regs.get(b) if name == 'BEQ': truth = (aval == bval) elif name == 'BNE': truth = (bval != aval) if truth: self.j('J', addr) else: self.pcinc() def mult(self, name, a, b): aval = self.regs.get(a) bval = self.regs.get(b) if name == 'MULT' or name == 'MULTU': aval *= bval # We're going to store high and low just cause hi = (aval & 0xFFFFFFFF00000000) >> 0x20 lo = (aval & 0x00000000FFFFFFFF) self.regs.set('hi', int(hi), special=True) self.regs.set('lo', lo, special=True) self.pcinc() def div(self, name, a, b): aval = self.regs.get(a) bval = self.regs.get(b) if name == 'DIV' or name == 'DIVU': hi = aval / bval lo = aval % bval self.regs.set('hi', hi, special=True) self.regs.set('lo', lo, special=True) self.pcinc() def mfhi(self, name, to): if name == 'MFHI': val = self.regs.get('hi') elif name == 'MFLO': val = self.regs.get('lo') self.regs.set(to, val) self.pcinc() def nop(self, name): self.pcinc() def _ret_conv(self, val): if type(val) == int: return val try: res = int(val) except: res = 0xdeadbeef return res def pyeval(self, name, code): code = code[1:-1] res = eval(code) if type(res) in [list, tuple]: res0, res1 = res res0 = self._ret_conv(res0) res1 = self._ret_conv(res1) self.regs.set('$v0', res0) self.regs.set('$v1', res1) else: res = self._ret_conv(res) self.regs.set('$v0', res) self.pcinc() def pycall(self, name, func): args = [ self.regs.get('$a0'), self.regs.get('$a1'), self.regs.get('$a2'), self.regs.get('$a3') ] args = repr(tuple(filter(lambda x: x != 0, args))) code = '"' + func + args + '"' self.pyeval("PYEVAL", code) def pyexec(self, name, code): eval(code) self.pcinc() def pysyscall(self, name, func): args = (self.regs.get('$a0'), self.regs.get('$a1'), self.regs.get('$a2'), self.regs.get('$a3')) code = '"' + func + '(self,' + repr(args) + ')"' self.pyeval("PYEVAL", code) def _addr_decode(self, addr): import re match = re.match("((\d+)?\((.*?)\)|(.*))", addr) if match: g = match.groups() if g[1]: offset = int(g[1]) else: offset = 0 if g[2]: reg = g[2] elif g[3]: reg = g[3] else: offset = 0 reg = '$0' return offset, reg def lw(self, name, reg, addr): off, srcreg = self._addr_decode(addr) addr = self.regs.get(srcreg) + off if name == 'LW': self.regs.set(reg, self.mem.get(addr, 4)) elif name == 'SW': self.mem.set(addr, 4, self.regs.get(reg)) self.pcinc() def loader(self, code): self.mem.rom(0, code) def execute(self, args): inst = args[0] self.cmds[inst](*args) def run(self): while True: pc = self.regs.get('pc') inst = self.mem.rawget(pc) ij = [] for e in inst: ij.append(str(e)) ij[0] = "\033[1m" + ij[0] + "\033[0m" dbg = "\t\033[30m\033[1;34m*\033[0;37m%5d:\033[0m\t%s\033[0m\n" % ( pc, " ".join(ij)) sys.stderr.write(dbg) self.execute(inst)