j-a

emu8086.py

j-a
Feb 26th, 2012
1,879
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import re
  2. import os
  3. from itertools import chain
  4.  
  5.  
  6. def sgn_ext(value):
  7.     return (value & 0xffff) | (0xff00 if (value & 0x0080) else 0)
  8.  
  9. def to_2compl(value, is_word):
  10.     if value & (1 << (nr_bits(is_word) - 1)) != 0:
  11.         value = abs(abs(value) - (1 << nr_bits(is_word)))
  12.     return value
  13.  
  14. def from_2compl(value, is_word):
  15.     if value & (1 << (nr_bits(is_word) - 1)):
  16.         return -((~(value - 1)) & ((1 << nr_bits(is_word)) - 1))
  17.     else:
  18.         return value
  19.  
  20. def nr_bytes(word):
  21.     return 2 if word else 1
  22.  
  23. def nr_bits(word):
  24.     return nr_bytes(word) * 8
  25.  
  26. def unpack_w(byte_stream):
  27.     return byte_stream[0] + (byte_stream[1] << 8)
  28.  
  29. def sub_2compl(a, b, is_word):
  30.     return (a + to_2compl(-b, is_word))
  31.  
  32. def hexword(value):
  33.     return "0x{0:0>4}".format(hex(value & 0xffff)[2:])
  34.  
  35. def hexbyte(value):
  36.     return "0x{0:0>2}".format(hex(value & 0x00ff)[2:])
  37.  
  38. def hexdump_from_mem(mem_bytes, separator=' '):
  39.     return separator.join(hexbyte(b) for b in mem_bytes)
  40.  
  41.  
  42.  
  43. class Ram():
  44.  
  45.     def __init__(self, size):
  46.         self._m = [0] * size
  47.  
  48.     def write(self, start, bytes):
  49.         for p in xrange(start, start + len(bytes)):
  50.             self._m[p] = bytes[p]
  51.  
  52.     def write_b(self, start, byte):
  53.         self._m[start] = byte
  54.  
  55.     def write_w(self, start, word):
  56.         self._m[start] = word & 0x00ff
  57.         self._m[start + 1] = (word & 0xff00) >> 8
  58.  
  59.     def read(self, start, length):
  60.         return self._m[start:start + length]
  61.  
  62.     def read_w(self, pos):
  63.         return unpack_w([self.read_b(pos), self.read_b(pos + 1)])
  64.  
  65.     def read_b(self, pos):
  66.         return self._m[pos]
  67.  
  68.     def hexdump(self, start, length):
  69.         return hexdump_from_mem(self.read(start, length))
  70.  
  71.  
  72. class WordStack():
  73.  
  74.     def __init__(self, size):
  75.         self._m = Ram(size)
  76.         self._sp = 0
  77.  
  78.     def push(self, value):
  79.         self._sp -= 2
  80.         self._m.write_w(self._sp, value)
  81.  
  82.     def pop(self):
  83.         self._sp += 2
  84.         return self._m.read_w(self._sp - 2)
  85.  
  86.     def pos(self):
  87.         return self._sp
  88.  
  89.     def set_pos(self, sp):
  90.         self._sp = sp
  91.  
  92.     def hexdump(self, length):
  93.         return self._m.hexdump(self._sp, length)
  94.  
  95.  
  96. class BaseState(object):
  97.     def __init__(self, ram=Ram(256 * 1024), stack=WordStack(64 * 1024)):
  98.         self._ram = ram
  99.         self._ip = 0
  100.         self._cf = 0
  101.         self._sf = 0
  102.         self._zf = 0
  103.         self._stack = stack
  104.         self._reg_val = [0] * 8
  105.  
  106.     def reg_value(self, reg_index):
  107.         return self._reg_val[reg_index]
  108.  
  109.     def read_ram(self, start, is_word):
  110.         if is_word:
  111.             return self._ram.read_w(start)
  112.         else:
  113.             return self._ram.read_b(start)
  114.  
  115.     def write_ram(self, start, value, is_word):
  116.         raise NotImplementedError
  117.  
  118.     def ram(self, start, length):
  119.         return self._ram.read(start, length)
  120.  
  121.     def instr_bytes(self):
  122.         return self._ram.read(self._ip, 6)
  123.  
  124.     def ip(self):
  125.         return self._ip
  126.  
  127.     def cf(self):
  128.         return self._cf
  129.  
  130.     def zf(self):
  131.         return self._zf
  132.  
  133.     def sf(self):
  134.         return self._sf
  135.  
  136.     def sp(self):
  137.         return self.reg_value(4)
  138.  
  139.     def ram_hexdump(self, address, length):
  140.         return self._ram.hexdump(address, length)
  141.  
  142.     def __str__(self):
  143.         def reg_values_str(is_word):
  144.             return "  ".join(
  145.                            "{0}:{2}{1}".format(
  146.                                 Register.name_from_index(index, is_word),
  147.                                 hexword(self._reg_val[index]) if is_word else
  148.                                 hexbyte(self._reg_val[index]),
  149.                                 '' if is_word else '  '
  150.                                )
  151.                            for index in xrange(8)
  152.                         )
  153.  
  154.         return ("CF:{0} ZF:{1} SF:{2} IP:{3}\n{4}\n{5}\n{6}"
  155.                 "".format(self.cf(), self.zf(), self.sf(), hexword(self.ip()),
  156.                           reg_values_str(True), reg_values_str(False),
  157.                           ("stack: {0} ..."
  158.                            "".format(self._stack.hexdump(8))
  159.                           )
  160.                          )
  161.                )
  162.  
  163.  
  164. class HaltState(BaseState):
  165.     def _nop(self, *args, **kwargs):
  166.         pass
  167.  
  168.     def halted(self):
  169.         return True
  170.  
  171.     def __getattr__(self, name):
  172.         return self._nop
  173.  
  174.  
  175. class State(BaseState):
  176.  
  177.     def halt(self):
  178.         self.__class__ = HaltState
  179.  
  180.     def halted(self):
  181.         return False
  182.  
  183.     def load_ram(self, start, mem):
  184.         mem = list(mem)
  185.         self._ram.write(start, mem)
  186.  
  187.     def move_ip(self, offset):
  188.         self._ip += offset
  189.  
  190.     def set_ip(self, ip):
  191.         self._ip = ip
  192.  
  193.     def set_cf(self, cf):
  194.         self._cf = 1 if cf else 0
  195.  
  196.     def write_ram(self, start, value, is_word):
  197.         if is_word:
  198.             self._ram.write_w(start, value & 0xffff)
  199.         else:
  200.             self._ram.write_b(start, value & 0x00ff)
  201.  
  202.  
  203.     def _zf_from_result(self, result, is_word):
  204.         return 1 if (result & ((1 << nr_bits(is_word)) - 1)) == 0 else 0
  205.  
  206.     def _sf_from_result(self, res, is_word):
  207.         return (res & (1 << (nr_bits(is_word) - 1))) >> (nr_bits(is_word) - 1)
  208.  
  209.     def set_flags_from_sub_operands(self, op1, op2, is_word):
  210.         result = sub_2compl(op1, op2, is_word)
  211.         self._cf = int(op2 > op1)
  212.         self._zf = self._zf_from_result(result, is_word)
  213.         self._sf = self._sf_from_result(result, is_word)
  214.  
  215.  
  216.     def set_flags_from_add_result(self, result, is_word):
  217.         self._cf = int(result > ((1 << nr_bits(is_word)) - 1))
  218.         self._zf = self._zf_from_result(result, is_word)
  219.         self._sf = self._sf_from_result(result, is_word)
  220.  
  221.  
  222.     def set_flags_from_logical_result(self, result, is_word):
  223.         # at least OK when only considering ZF, SF, CF
  224.         self.set_flags_from_add_result(result, is_word)
  225.  
  226.     def set_flags_from_inc_dec_result(self, result, is_word):
  227.         # at least OK when only considering ZF, SF, CF
  228.         cf = self.cf()
  229.         self.set_flags_from_add_result(result, is_word)
  230.         self._cf = cf
  231.  
  232.  
  233.     def set_reg_value(self, reg_index, value, is_word):
  234.         if is_word:
  235.             self._reg_val[reg_index] = value & 0xffff
  236.         else:
  237.             self._reg_val[reg_index] = ((self._reg_val[reg_index] & 0xff00) +
  238.                                          (value & 0xff)
  239.                                        )
  240.         self._stack.set_pos(self.sp())
  241.  
  242.  
  243.     def push_stack(self, value):
  244.         self._stack.push(value)
  245.         self.set_reg_value(4, self._stack.pos(), True)
  246.  
  247.     def pop_stack(self):
  248.         t = self._stack.pop()
  249.         self.set_reg_value(4, self._stack.pos(), True)
  250.         return t
  251.  
  252.  
  253. class Machine():
  254.  
  255.     class Console():
  256.         def __init__(self, rows, cols):
  257.             self.rows = rows
  258.             self.cols = cols
  259.  
  260.         def dbg_fill_display(self, display):
  261.             mem = ''.join(str(y % 10) * self.cols for y in xrange(self.rows))
  262.             self.update(mem, display)
  263.  
  264.         def update(self, screen_mem, display):
  265.             for y in xrange(self.rows):
  266.                 for x in xrange(self.cols):
  267.                     display.set_char(x, y, screen_mem[y * self.cols + x])
  268.             display.refresh()
  269.  
  270.  
  271.     def __init__(self, state, disasm):
  272.         self._console = Machine.Console(self.rows(), self.cols())
  273.         self._disasm = disasm
  274.         self._state = state
  275.  
  276.     def rows(self):
  277.         return 25
  278.  
  279.     def cols(self):
  280.         return 80
  281.  
  282.     def load(self, program):
  283.         self._state.load_ram(0, (ord(c) for c in program))
  284.         self._ip = 0
  285.         self._last_ip = len(program)
  286.  
  287.  
  288.     def _screen_mem(self):
  289.         return self._state.ram(int('0x8000', 16), self.rows()*self.cols())
  290.  
  291.  
  292.     def _exec_instr(self):
  293.         instr = self._disasm.decode_instr(self._state.instr_bytes())
  294.         self._state.move_ip(instr.length())
  295.         instr.execute(self._state)
  296.  
  297.     def state(self):
  298.         return self._state
  299.  
  300.     def next_clock(self, console_display):
  301.         if console_display is not None:
  302.             self._console.update(self._screen_mem(), console_display)
  303.         self._exec_instr()
  304.         return self._state.ip() != self._last_ip
  305.  
  306.  
  307. class Register():
  308.     _wname_from_bits = {
  309.             '000':'AX',
  310.             '001':'CX',
  311.             '010':'DX',
  312.             '011':'BX',
  313.             '100':'SP',
  314.             '101':'BP',
  315.             '110':'SI',
  316.             '111':'DI',
  317.         }
  318.     _bname_from_bits = {
  319.             '000':'AL',
  320.             '001':'CL',
  321.             '010':'DL',
  322.             '011':'BL',
  323.             '100':'AH',
  324.             '101':'CH',
  325.             '110':'DH',
  326.             '111':'BH',
  327.         }
  328.  
  329.     @classmethod
  330.     def index_from_name(cls, name):
  331.         return int(Register.bits_from_name_dict()[name], 2)
  332.  
  333.     @classmethod
  334.     def bits_from_name_dict(cls):
  335.         return dict((v, u) for u, v in (chain(cls._wname_from_bits.items(),
  336.                                               cls._bname_from_bits.items(),
  337.                                               )
  338.                                         )
  339.                    )
  340.  
  341.     @classmethod
  342.     def name_from_index(cls, index, is_word):
  343.         return {
  344.                 True: cls._wname_from_bits[bin(index)[2:].rjust(3, '0')],
  345.                 False: cls._bname_from_bits[bin(index)[2:].rjust(3, '0')],
  346.                 }[is_word]
  347.  
  348.     def __init__(self, bits):
  349.         self._bits = bits
  350.  
  351.     def index(self):
  352.         return int(self._bits, 2)
  353.  
  354.     def name(self, is_word):
  355.         return {
  356.                 True:self._wname_from_bits[self._bits],
  357.                 False:self._bname_from_bits[self._bits],
  358.             }[is_word]
  359.  
  360.  
  361.     def __str__(self):
  362.         return self.name(True)
  363.  
  364.  
  365.  
  366. class EffectiveAddress(object):
  367.  
  368.     def __init__(self, register1, register2, disp):
  369.         self._reg1 = register1
  370.         self._reg2 = register2
  371.         self._disp = disp
  372.         if self._reg1 is None:
  373.             self.__class__ = EffectiveAddressDispOnly
  374.         elif self._reg2 is None:
  375.             self.__class__ = EffectiveAddressDispAndReg1
  376.         else:
  377.             self.__class__ = EffectiveAddressDispAndReg1AndReg2
  378.  
  379.     def _str_add_disp(self):
  380.         return '' if self._disp == 0 else ' + {0}'.format(hex(self._disp))
  381.  
  382.  
  383. class EffectiveAddressDispAndReg1AndReg2(EffectiveAddress):
  384.     def __str__(self):
  385.         return '[({0}) + ({1}){2}]'.format(self._reg1,
  386.                                            self._reg2,
  387.                                            self._str_add_disp()
  388.                                           )
  389.  
  390.     def address(self, machine_state):
  391.         return (machine_state.reg_value(self._reg1.index()) +
  392.                 machine_state.reg_value(self._reg2.index()) +
  393.                 self._disp
  394.                 )
  395.  
  396.  
  397. class EffectiveAddressDispAndReg1(EffectiveAddress):
  398.     def __str__(self):
  399.         return '[({0}){1}]'.format(self._reg1, self._str_add_disp())
  400.  
  401.     def address(self, machine_state):
  402.         return machine_state.reg_value(self._reg1.index()) + self._disp
  403.  
  404.  
  405. class EffectiveAddressDispOnly(EffectiveAddress):
  406.     def __str__(self):
  407.         return '[{0}]'.format(hex(self._disp))
  408.  
  409.     def address(self, machine_state):
  410.         return self._disp
  411.  
  412.  
  413. def sub_upd_flags(op1, op2, is_word, machine_state):
  414.     machine_state.set_flags_from_sub_operands(op1, op2, is_word)
  415.     return sub_2compl(op1, op2, is_word)
  416.  
  417.  
  418.  
  419. class BaseOp(object):
  420.  
  421.     def __init__(self, instr_length, name):
  422.         self._instr_length = instr_length
  423.         self._name = name
  424.         if hasattr(self, "exec_{0}".format(name)):
  425.             self.execute = getattr(self, "exec_{0}".format(name))
  426.  
  427.     def length(self):
  428.         return self._instr_length
  429.  
  430.     def __str__(self):
  431.         return "{0}".format(self._name)
  432.  
  433.  
  434. class Op_Reg_Immediate(BaseOp):
  435.  
  436.     def exec_cmp(self, machine_state):
  437.         sub_upd_flags(machine_state.reg_value(self._reg.index()),
  438.                       self._im,
  439.                       self._is_word,
  440.                       machine_state
  441.                     )
  442.  
  443.  
  444.     def exec_sub(self, machine_state):
  445.         machine_state.set_reg_value(
  446.                             self._reg.index(),
  447.                             sub_upd_flags(
  448.                                  machine_state.reg_value(self._reg.index()),
  449.                                  self._im,
  450.                                  self._is_word,
  451.                                  machine_state
  452.                             ),
  453.                             self._is_word,
  454.                         )
  455.  
  456.     def exec_add(self, machine_state):
  457.         result = machine_state.reg_value(self._reg.index()) + self._im
  458.         machine_state.set_reg_value(self._reg.index(), result, self._is_word)
  459.         machine_state.set_flags_from_add_result(result, self._is_word)
  460.  
  461.     def exec_mov(self, machine_state):
  462.         machine_state.set_reg_value(self._reg.index(), self._im, self._is_word)
  463.  
  464.     def exec_adc(self, machine_state):
  465.         result = (machine_state.reg_value(self._reg.index()) +
  466.                   self._im +
  467.                   machine_state.cf()
  468.                  )
  469.         machine_state.set_reg_value(self._reg.index(), result, self._is_word)
  470.         machine_state.set_flags_from_add_result(result, self._is_word)
  471.  
  472.     def exec_and(self, machine_state):
  473.         result = machine_state.reg_value(self._reg.index()) & self._im
  474.         machine_state.set_reg_value(self._reg.index(), result, self._is_word)
  475.         machine_state.set_flags_from_logical_result(result, self._is_word)
  476.  
  477.     def __init__(self, instr_length, name, register, immediate, is_word):
  478.         super(Op_Reg_Immediate, self).__init__(instr_length, name)
  479.         self._im = immediate
  480.         self._reg = register
  481.         self._is_word = is_word
  482.  
  483.     def __str__(self):
  484.         return "{0} {1}, {2}".format(self._name,
  485.                                      self._reg.name(self._is_word),
  486.                                      hex(self._im)
  487.                                      )
  488.  
  489.  
  490. class Nop(BaseOp):
  491.     def __str__(self):
  492.         return "nop"
  493.  
  494.     def execute(self, machine_state):
  495.         pass
  496.  
  497.  
  498. class Op_Reg_Reg(BaseOp):
  499.  
  500.  
  501.     def _logical_reg_reg(self, machine_state, log_op):
  502.         result = log_op(machine_state.reg_value(self._reg1.index()),
  503.                         machine_state.reg_value(self._reg2.index())
  504.                        )
  505.         machine_state.set_reg_value(self._reg1.index(), result, self._is_word)
  506.         machine_state.set_flags_from_logical_result(result, self._is_word)
  507.  
  508.     def exec_xor(self, machine_state):
  509.         self._logical_reg_reg(machine_state, lambda a, b: a ^ b)
  510.  
  511.     def exec_or(self, machine_state):
  512.         self._logical_reg_reg(machine_state, lambda a, b: a | b)
  513.  
  514.     def exec_and(self, machine_state):
  515.         self._logical_reg_reg(machine_state, lambda a, b: a & b)
  516.  
  517.     def exec_cmp(self, machine_state):
  518.         sub_upd_flags(machine_state.reg_value(self._reg1.index()),
  519.                       machine_state.reg_value(self._reg2.index()),
  520.                       self._is_word,
  521.                       machine_state
  522.                     )
  523.  
  524.  
  525.     def exec_add(self, machine_state):
  526.         result = (machine_state.reg_value(self._reg1.index()) +
  527.                   machine_state.reg_value(self._reg2.index())
  528.                  )
  529.         machine_state.set_reg_value(self._reg1.index(), result, self._is_word)
  530.         machine_state.set_flags_from_add_result(result, self._is_word)
  531.  
  532.     def exec_sbb(self, machine_state):
  533.         machine_state.set_reg_value(
  534.                             self._reg1.index(),
  535.                             sub_upd_flags(
  536.                                  machine_state.reg_value(self._reg1.index()),
  537.                                  (machine_state.reg_value(self._reg2.index()) +
  538.                                   machine_state.cf()
  539.                                  ),
  540.                                  self._is_word,
  541.                                  machine_state
  542.                             ),
  543.                             self._is_word,
  544.                         )
  545.  
  546.  
  547.     def exec_xchg(self, machine_state):
  548.         rv1 = machine_state.reg_value(self._reg1.index())
  549.         rv2 = machine_state.reg_value(self._reg2.index())
  550.         machine_state.set_reg_value(self._reg1.index(), rv2, self._is_word)
  551.         machine_state.set_reg_value(self._reg2.index(), rv1, self._is_word)
  552.  
  553.  
  554.     def exec_mov(self, machine_state):
  555.         machine_state.set_reg_value(
  556.                             self._reg1.index(),
  557.                             machine_state.reg_value(self._reg2.index()),
  558.                             self._is_word)
  559.  
  560.  
  561.     def __init__(self, instr_length, name, register1, register2, is_word):
  562.         super(Op_Reg_Reg, self).__init__(instr_length, name)
  563.         self._reg1 = register1
  564.         self._reg2 = register2
  565.         self._is_word = is_word
  566.         if self._name == 'xchg' and self._reg1.index() == self._reg2.index():
  567.             self.__class__ = Nop
  568.  
  569.  
  570.     def __str__(self):
  571.         return "{0} {1}, {2}".format(self._name,
  572.                                      self._reg1.name(self._is_word),
  573.                                      self._reg2.name(self._is_word),
  574.                                      )
  575.  
  576.  
  577. class Op_Ea_Immediate(BaseOp):
  578.  
  579.     def __init__(self, instr_length, name, ea, immediate, is_word):
  580.         super(Op_Ea_Immediate, self).__init__(instr_length, name)
  581.         self._ea = ea
  582.         self._im = immediate
  583.         self._word = is_word
  584.  
  585.     def exec_cmp(self, machine_state):
  586.         sub_upd_flags(
  587.            machine_state.read_ram(self._ea.address(machine_state), self._word),
  588.            self._im,
  589.            self._word,
  590.            machine_state
  591.           )
  592.  
  593.  
  594.     def exec_add(self, machine_state):
  595.         ea_addr = self._ea.address(machine_state)
  596.         result = machine_state.read_ram(ea_addr, self._word) + self._im
  597.         machine_state.write_ram(ea_addr, result, self._word)
  598.         machine_state.set_flags_from_add_result(result, self._word)
  599.  
  600.     def exec_or(self, machine_state):
  601.         ea_addr = self._ea.address(machine_state)
  602.         result = machine_state.read_ram(ea_addr, self._word) | self._im
  603.         machine_state.write_ram(ea_addr, result, self._word)
  604.         machine_state.set_flags_from_logical_result(result, self._word)
  605.  
  606.  
  607.     def exec_mov(self, machine_state):
  608.         machine_state.write_ram(
  609.                         self._ea.address(machine_state), self._im, self._word
  610.                        )
  611.  
  612.  
  613.     def __str__(self):
  614.         return "{0} {3} {1}, {2}".format(self._name,
  615.                                            self._ea,
  616.                                            hex(self._im),
  617.                                            'word' if self._word else 'byte')
  618.  
  619.  
  620.  
  621. class Op_Ea_Reg(BaseOp):
  622.  
  623.     def exec_mov(self, machine_state):
  624.         machine_state.write_ram(
  625.                                 self._ea.address(machine_state),
  626.                                 machine_state.reg_value(self._reg.index()),
  627.                                 self._word
  628.                                )
  629.  
  630.     def exec_and(self, machine_state):
  631.         ea_addr = self._ea.address(machine_state)
  632.         result = (machine_state.read_ram(ea_addr, self._word) &
  633.                   machine_state.reg_value(self._reg.index())
  634.                   )
  635.         machine_state.write_ram(ea_addr, result, self._word)
  636.         machine_state.set_flags_from_logical_result(result, self._word)
  637.  
  638.     def exec_add(self, machine_state):
  639.         ea_addr = self._ea.address(machine_state)
  640.         result = (machine_state.read_ram(ea_addr, self._word) +
  641.                   machine_state.reg_value(self._reg.index())
  642.                   )
  643.         machine_state.write_ram(ea_addr, result, self._word)
  644.         machine_state.set_flags_from_add_result(result, self._word)
  645.  
  646.  
  647.     def exec_sub(self, machine_state):
  648.         machine_state.write_ram(
  649.                 self._ea.address(machine_state),
  650.                 sub_upd_flags(
  651.                      machine_state.read_ram(self._ea.address(machine_state),
  652.                                             self._word
  653.                                            ),
  654.                      machine_state.reg_value(self._reg.index()),
  655.                      self._word,
  656.                      machine_state
  657.                 ),
  658.                 self._word
  659.         )
  660.  
  661.  
  662.     def __init__(self, instr_length, name, reg, ea, is_word):
  663.         super(Op_Ea_Reg, self).__init__(instr_length, name)
  664.         self._ea = ea
  665.         self._name = name
  666.         self._reg = reg
  667.         self._word = is_word
  668.  
  669.  
  670.     def __str__(self):
  671.         return "{0} {3} {1}, {2}".format(self._name,
  672.                                            self._ea,
  673.                                            self._reg.name(self._word),
  674.                                            'word' if self._word else 'byte')
  675.  
  676.  
  677. class Op_Reg_Ea(BaseOp):
  678.  
  679.     def exec_mov(self, machine_state):
  680.         machine_state.set_reg_value(self._reg.index(),
  681.                                     machine_state.read_ram(
  682.                                            self._ea.address(machine_state),
  683.                                            self._word
  684.                                        ),
  685.                                     self._word
  686.                                     )
  687.  
  688.     def __init__(self, instr_length, name, reg, ea, is_word):
  689.         super(Op_Reg_Ea, self).__init__(instr_length, name)
  690.         self._ea = ea
  691.         self._reg = reg
  692.         self._word = is_word
  693.  
  694.  
  695.     def __str__(self):
  696.         return "{0} {3} {2}, {1}".format(self._name,
  697.                                            self._ea,
  698.                                            self._reg.name(self._word),
  699.                                            'word' if self._word else 'byte')
  700.  
  701.  
  702.  
  703. class Op_Reg(BaseOp):
  704.  
  705.  
  706.     def exec_dec(self, machine_state):
  707.         machine_state.set_reg_value(
  708.             self._reg.index(),
  709.             sub_2compl(machine_state.reg_value(self._reg.index()), 1, self._word),
  710.             self._word
  711.         )
  712.         machine_state.set_flags_from_inc_dec_result(machine_state.reg_value(
  713.                                                             self._reg.index()
  714.                                                         ),
  715.                                                     self._word
  716.                                                 )
  717.  
  718.     def exec_inc(self, machine_state):
  719.         machine_state.set_reg_value(
  720.                 self._reg.index(),
  721.                 machine_state.reg_value(self._reg.index()) + 1,
  722.                 self._word
  723.             )
  724.         machine_state.set_flags_from_inc_dec_result(machine_state.reg_value(
  725.                                                             self._reg.index()
  726.                                                         ),
  727.                                                     self._word
  728.                                                    )
  729.  
  730.     def exec_push(self, machine_state):
  731.         machine_state.push_stack(machine_state.reg_value(self._reg.index()))
  732.  
  733.     def exec_pop(self, machine_state):
  734.         machine_state.set_reg_value(self._reg.index(),
  735.                                     machine_state.pop_stack(),
  736.                                     self._word)
  737.  
  738.  
  739.     def __init__(self, instr_length, name, reg, is_word):
  740.         super(Op_Reg, self).__init__(instr_length, name)
  741.         self._reg = reg
  742.         self._word = is_word
  743.  
  744.     def __str__(self):
  745.         return "{0} {1}".format(self._name,
  746.                                 self._reg.name(self._word))
  747.  
  748.  
  749.  
  750.  
  751. class Op_Disp(BaseOp):
  752.  
  753.     def exec_jz(self, machine_state):
  754.         if machine_state.zf():
  755.             machine_state.move_ip(self._addr)
  756.  
  757.     def exec_jc(self, machine_state):
  758.         if machine_state.cf():
  759.             machine_state.move_ip(self._addr)
  760.  
  761.     def exec_jnz(self, machine_state):
  762.         if not machine_state.zf():
  763.             machine_state.move_ip(self._addr)
  764.  
  765.     def exec_jnbe(self, machine_state):
  766.         if not machine_state.zf() and not machine_state.cf():
  767.             machine_state.move_ip(self._addr)
  768.  
  769.     def exec_jns(self, machine_state):
  770.         if not machine_state.sf():
  771.             machine_state.move_ip(self._addr)
  772.  
  773.     def exec_jbe(self, machine_state):
  774.         if machine_state.cf() or machine_state.zf():
  775.             machine_state.move_ip(self._addr)
  776.  
  777.     def exec_jmp(self, machine_state):
  778.         machine_state.move_ip(self._addr)
  779.  
  780.  
  781.     def exec_call(self, machine_state):
  782.         machine_state.push_stack(machine_state.ip())
  783.         machine_state.move_ip(self._addr)
  784.  
  785.  
  786.     def __init__(self, instr_length, name, address):
  787.         super(Op_Disp, self).__init__(instr_length, name)
  788.         self._is_word = True if instr_length == 3 else False
  789.         self._addr = from_2compl(address, self._is_word)
  790.  
  791.     def rel_addr(self):
  792.         return self._addr
  793.  
  794.     def __str__(self):
  795.         return "{0} {1}".format(self._name, hex(self._addr))
  796.  
  797.  
  798.  
  799.  
  800. class Op_NoArgs(BaseOp):
  801.  
  802.     def exec_hlt(self, machine_state):
  803.         machine_state.halt()
  804.  
  805.     def exec_ret(self, machine_state):
  806.         machine_state.set_ip(machine_state.pop_stack())
  807.  
  808.     def exec_stc(self, machine_state):
  809.         machine_state.set_cf(1)
  810.  
  811.     def __init__(self, instr_length, name):
  812.         super(Op_NoArgs, self).__init__(instr_length, name)
  813.  
  814.  
  815. class Unknown_Op(BaseOp):
  816.     def __init__(self):
  817.         super(Unknown_Op, self).__init__(1, 'UNKNOWN')
  818.  
  819.  
  820.  
  821. class Unpacker():
  822.  
  823.     def __init__(self, bitstr, byte_offset=0):
  824.         self._bstr = bitstr[byte_offset * 8:]
  825.  
  826.     def dispatch(self, mod, rm):
  827.         if mod == '00' and rm != '110':
  828.             return 0
  829.         elif mod == '00' and rm == '110':
  830.             return self.unpack_w()
  831.         else:
  832.             return {
  833.                 '01':self.unpack_se_b(),
  834.                 '10':self.unpack_w()
  835.                }[mod]
  836.  
  837.  
  838.     def unpack_w(self, start=0):
  839.         return unpack_w([self._peek(start), self._peek(start + 1)])
  840.  
  841.     def unpack_b(self, start=0):
  842.         return self._peek(start)
  843.  
  844.     def unpack_se_b(self, start=0):
  845.         return sgn_ext(self.unpack_b(start))
  846.  
  847.     def unpack(self, start, is_word, do_sgn_ext=False):
  848.         if is_word:
  849.             return self.unpack_w(start)
  850.         elif do_sgn_ext:
  851.             return self.unpack_se_b(start)
  852.         else:
  853.             return self.unpack_b(start)
  854.  
  855.     def _peek(self, offset):
  856.         return int(self._bstr[offset * 8:(offset + 1) * 8], 2)
  857.  
  858.  
  859. class DisAsm():
  860.  
  861.     def __init__(self):
  862.         self._dispatch_from_re = dict(
  863.                     (
  864.                      re.compile(
  865.                                 p.format(
  866.                                          w="(?P<w>[01]{1})",
  867.                                          sw="(?P<sw>[01]{2})",
  868.                                          dw="(?P<dw>[01]{2})",
  869.                                          mod="(?P<mod>[01]{2})",
  870.                                          reg="(?P<reg>[01]{3})",
  871.                                          rm="(?P<rm>[01]{3})",
  872.                                          disp="(?P<disp>[01]{8})"
  873.                                 )
  874.                             ),
  875.                      f
  876.                     )
  877.                     for p, f in self.instruction_dict().items()
  878.                )
  879.  
  880.  
  881.     def instruction_dict(self):
  882.  
  883.         def is_word(w):
  884.             return w == '1'
  885.  
  886.         def unpacker_from_bitstr(bitstr, start):
  887.             return Unpacker(bitstr[start * 8:(start + 6) * 8])
  888.  
  889.         def unpack_w(match, start):
  890.             return unpacker_from_bitstr(match.string, start).unpack_w()
  891.  
  892.         def unpack_b(match, start):
  893.             return unpacker_from_bitstr(match.string, start).unpack_b()
  894.  
  895.         def unpack(match, start, is_word):
  896.             return unpacker_from_bitstr(match.string, start).unpack(0, is_word)
  897.  
  898.         def op_w_acc(name, match):
  899.             return Op_Reg_Immediate(
  900.                     1 + nr_bytes(is_word(match.group('w'))),
  901.                     name,
  902.                     Register('000'),
  903.                     unpack(match, 1, is_word(match.group('w'))),
  904.                     is_word(match.group('w'))
  905.                    )
  906.  
  907.  
  908.         def create_ea(mod, rm, dispatch):
  909.  
  910.             def reg_by_name(name):
  911.                 return Register(Register.bits_from_name_dict()[name])
  912.  
  913.             def reg1_reg2():
  914.                 return {
  915.                         '000': (reg_by_name('BX'), reg_by_name('SI')),
  916.                         '001': (reg_by_name('BX'), reg_by_name('DI')),
  917.                         '010': (reg_by_name('BP'), reg_by_name('SI')),
  918.                         '011': (reg_by_name('BP'), reg_by_name('DI')),
  919.                         '100': (reg_by_name('SI'), None),
  920.                         '101': (reg_by_name('DI'), None),
  921.                         '110': (reg_by_name('BP'), None),
  922.                         '111': (reg_by_name('BX'), None),
  923.                     }[rm]
  924.  
  925.             if mod == '00' and rm == '110':
  926.                 return EffectiveAddress(None, None, dispatch)
  927.             else:
  928.                 return EffectiveAddress(reg1_reg2()[0],
  929.                                         reg1_reg2()[1],
  930.                                         dispatch
  931.                                        )
  932.  
  933.  
  934.         def _mnemonic_i_rm(instr_length, name, is_word, mod, i, rm, unpacker):
  935.             if mod == '11':
  936.                 return Op_Reg_Immediate(instr_length,
  937.                                         name,
  938.                                         Register(rm),
  939.                                         i,
  940.                                         is_word
  941.                                        )
  942.             else:
  943.                 return Op_Ea_Immediate(
  944.                                instr_length,
  945.                                name,
  946.                                create_ea(mod, rm, unpacker.dispatch(mod, rm)),
  947.                                i,
  948.                                is_word
  949.                             )
  950.  
  951.  
  952.         def _sw_mod_rm__op_i_rm(name, sw, mod, rm, unpacker):
  953.             return _mnemonic_i_rm(
  954.                       2 + _nr_ea_bytes(mod, rm) + nr_bytes(sw == '01'),
  955.                       name,
  956.                       sw[1] == '1',
  957.                       mod,
  958.                       unpacker.unpack(_data_byte_offset(mod, rm),
  959.                                       sw == '01', sw[0] == '1'),
  960.                       rm,
  961.                       unpacker
  962.                      )
  963.  
  964.  
  965.         def op_sw_mod_rm_im(name, match):
  966.             return _sw_mod_rm__op_i_rm(name,
  967.                                      match.group('sw'),
  968.                                      match.group('mod'),
  969.                                      match.group('rm'),
  970.                                      unpacker_from_bitstr(match.string, 2)
  971.                                     )
  972.  
  973.         def op_w_mod_rm_im(name, match):
  974.             return _sw_mod_rm__op_i_rm(name,
  975.                                      '0' + match.group('w'),
  976.                                      match.group('mod'),
  977.                                      match.group('rm'),
  978.                                      unpacker_from_bitstr(match.string, 2)
  979.                                     )
  980.  
  981.         def _nr_ea_bytes(mod, rm):
  982.             return {
  983.                      '00': 2 if rm == '110' else 0,
  984.                      '01': 1,
  985.                      '10': 2,
  986.                      '11': 0,
  987.              }[mod]
  988.  
  989.  
  990.         def _data_byte_offset(mod, rm):
  991.             return _nr_ea_bytes(mod, rm)
  992.  
  993.  
  994.         def op_sw_mod_rm(match, name):
  995.             return op_sw_mod_rm_im(name, match)
  996.  
  997.         def _mnemonic_rm_r(instr_length, name, to_reg, is_word, mod, rm, r,
  998.                            unpacker):
  999.             if mod == '11':
  1000.                 return Op_Reg_Reg(instr_length,
  1001.                                   name,
  1002.                                   Register(rm),
  1003.                                   Register(r),
  1004.                                   is_word
  1005.                                 )
  1006.             else:
  1007.                 if to_reg:
  1008.                     return Op_Reg_Ea(instr_length,
  1009.                              name,
  1010.                              Register(r),
  1011.                              create_ea(mod, rm, unpacker.dispatch(mod, rm)),
  1012.                              is_word
  1013.                             )
  1014.                 else:
  1015.                     return Op_Ea_Reg(instr_length,
  1016.                              name,
  1017.                              Register(r),
  1018.                              create_ea(mod, rm, unpacker.dispatch(mod, rm)),
  1019.                              is_word
  1020.                             )
  1021.  
  1022.         def op_dw_mod_reg_rm(name, match):
  1023.             return _mnemonic_rm_r(
  1024.                            (2 +
  1025.                             _nr_ea_bytes(match.group('mod'), match.group('rm'))
  1026.                            ),
  1027.                            name,
  1028.                            to_reg=match.group('dw')[0] == '1',
  1029.                            is_word=match.group('dw')[1] == '1',
  1030.                            mod=match.group('mod'),
  1031.                            rm=match.group('rm'),
  1032.                            r=match.group('reg'),
  1033.                            unpacker=unpacker_from_bitstr(match.string, 2)
  1034.                           )
  1035.  
  1036.         def op_w_mod_rm(name, match):
  1037.             w = match.group('w')
  1038.             mod = match.group('mod')
  1039.             rm = match.group('rm')
  1040.             if mod == '11':
  1041.                 return Op_Reg(2, name, Register(rm), w == '1')
  1042.             else:
  1043.                 raise Exception("Not implemented")
  1044.  
  1045.         def op_disp_byte(name, match):
  1046.             return Op_Disp(2, name, unpack_b(match, 1))
  1047.  
  1048.         def op_disp_word(name, match):
  1049.             return Op_Disp(3, name, unpack_w(match, 1))
  1050.  
  1051.         def op_no_args(name, match):
  1052.             return Op_NoArgs(1, name)
  1053.  
  1054.         def op_reg(name, match):
  1055.             return Op_Reg(1, name, Register(match.group('reg')), is_word=True)
  1056.  
  1057.         def op_reg_acc(name, match):
  1058.             return Op_Reg_Reg(1,
  1059.                                name,
  1060.                                Register('000'),
  1061.                                Register(match.group('reg')),
  1062.                                is_word=True
  1063.                               )
  1064.  
  1065.         def op_w_mod_reg_rm(name, match):
  1066.             return _mnemonic_rm_r(2,
  1067.                                   name,
  1068.                                   to_reg=True,
  1069.                                   is_word=match.group('w') == '1',
  1070.                                   mod=match.group('mod'),
  1071.                                   rm=match.group('rm'),
  1072.                                   r=match.group('reg'),
  1073.                                   unpacker=unpacker_from_bitstr(match.string, 2)
  1074.                                  )
  1075.  
  1076.  
  1077.         def _w_reg_im(name, w, reg, unpacker):
  1078.             return _mnemonic_i_rm(1 + nr_bytes(is_word(w)),
  1079.                                   name, w == '1',
  1080.                                   '11',
  1081.                                   unpacker.unpack(0, is_word(w)),
  1082.                                   reg,
  1083.                                   unpacker
  1084.                                  )
  1085.  
  1086.  
  1087.         def op_w_reg_im(name, match):
  1088.             return _w_reg_im(name,
  1089.                              match.group('w'),
  1090.                              match.group('reg'),
  1091.                              unpacker_from_bitstr(match.string, 1)
  1092.                            )
  1093.  
  1094.  
  1095.         return {
  1096.             "100000{sw}{mod}111{rm}": lambda m: op_sw_mod_rm(m, "cmp"),
  1097.             "01110100{disp}": lambda m: op_disp_byte('jz', m),
  1098.             "01110101{disp}": lambda m: op_disp_byte('jnz', m),
  1099.             "11110100": lambda m: op_no_args("hlt", m),
  1100.             "1011{w}{reg}": lambda m: op_w_reg_im("mov", m),
  1101.             "01001{reg}": lambda m: op_reg("dec", m),
  1102.             "11101000{reg}": lambda m: op_disp_word("call", m),
  1103.             "01000{reg}": lambda m: op_reg("inc", m),
  1104.             "001100{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("xor", m),
  1105.             "000010{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("or", m),
  1106.             "01110010{disp}": lambda m: op_disp_byte('jc', m),
  1107.             "001110{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("cmp", m),
  1108.             "01110110{disp}": lambda m: op_disp_byte('jbe', m),
  1109.             "000000{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("add", m),
  1110.             "100000{sw}{mod}010{rm}": lambda m: op_sw_mod_rm(m, "adc"),
  1111.             "01111001{disp}": lambda m: op_disp_byte('jns', m),
  1112.             "01010{reg}": lambda m: op_reg("push", m),
  1113.             "100000{sw}{mod}100{rm}": # NOTE!! s always 0 according to http://datasheets.chipdb.org/Intel/x86/808x/datashts/8086/231455-006.pdf but not in the codegolf code??
  1114.                             lambda m: op_sw_mod_rm(m, "and"),
  1115.             "01011{reg}": lambda m: op_reg("pop", m),
  1116.             "11111001": lambda m: op_no_args("stc", m),
  1117.             "000110{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("sbb", m),
  1118.             "11000011": lambda m: op_no_args("ret", m),
  1119.             "11101011": lambda m: op_disp_byte('jmp', m),
  1120.             "1111111{w}{mod}000{rm}": lambda m: op_w_mod_rm("inc", m),
  1121.             "0011110{w}": lambda m: op_w_acc("cmp", m),
  1122.             "1100011{w}{mod}000{rm}": lambda m: op_w_mod_rm_im("mov", m),
  1123.             "1111111{w}{mod}001{rm}": lambda m: op_w_mod_rm("dec", m),
  1124.             "100000{sw}{mod}000{rm}": lambda m: op_sw_mod_rm(m, "add"),
  1125.             "10010{reg}": lambda m: op_reg_acc("xchg", m),
  1126.             "100010{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("mov", m),
  1127.             "1000000{w}{mod}001{rm}": lambda m: op_w_mod_rm_im("or", m),
  1128.             "1000011{w}{mod}{reg}{rm}": lambda m: op_w_mod_reg_rm("xchg", m),
  1129.             "001000{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("and", m),
  1130.             "100000{sw}{mod}101{rm}": lambda m: op_sw_mod_rm_im("sub", m),
  1131.             "001010{dw}{mod}{reg}{rm}": lambda m: op_dw_mod_reg_rm("sub", m),
  1132.             "01110111{disp}": lambda m: op_disp_byte('jnbe', m),
  1133.             "0000010{w}": lambda m: op_w_acc("add", m),
  1134.         }
  1135.  
  1136.  
  1137.     def decode_instr(self, bytes):
  1138.         def instr_bitstr():
  1139.             return ''.join(bin(b)[2:].rjust(8, '0') for b in bytes[:6])
  1140.         for p, dispatcher in self._dispatch_from_re.iteritems():
  1141.             if p.match(instr_bitstr()):
  1142.                 return dispatcher(p.match(instr_bitstr()))
  1143.         return Unknown_Op()
  1144.  
  1145.  
  1146.     def instructions(self, program_bytes):
  1147.         pc = 0
  1148.         while pc < len(program_bytes):
  1149.             instr = self.decode_instr(program_bytes[pc:pc + 6])
  1150.             pc += instr.length()
  1151.             yield instr
  1152.  
  1153.  
  1154. class RunToAnyBreakPoint(object):
  1155.  
  1156.     def __init__(self, breaks, state_after):
  1157.         self._breaks = breaks
  1158.         self._breaked = False
  1159.         self._next_state = state_after
  1160.  
  1161.     def next_state(self):
  1162.         return self if not self._breaked else self._next_state
  1163.  
  1164.     def update(self, machine):
  1165.         if self._breaked:
  1166.             return
  1167.         if machine.state().ip() not in self._breaks:
  1168.             machine.next_clock(None)
  1169.         else:
  1170.             self._breaked = True
  1171.  
  1172.  
  1173. class InteractiveDebug(object):
  1174.  
  1175.     def __init__(self):
  1176.         self._run_to_break = False
  1177.         self._breaks = []
  1178.         self._next_state = self
  1179.  
  1180.     def next_state(self):
  1181.         return self._next_state
  1182.  
  1183.     def see_ram(self, machine_state, address):
  1184.         print "M {0}: {1} ...".format(
  1185.                           hex(address),
  1186.                           machine_state.ram_hexdump(address, 12)
  1187.                         )
  1188.  
  1189.     def _run_to_next_state(self):
  1190.         if len(self._breaks) != 0:
  1191.             self._next_state = RunToAnyBreakPoint(self._breaks, self)
  1192.         else:
  1193.             self._next_state = self
  1194.  
  1195.     def update(self, machine):
  1196.         print machine.state()
  1197.         if machine.state().halted():
  1198.             return
  1199.         print DisAsm().decode_instr(machine.state().instr_bytes())
  1200.         machine.next_clock(None)
  1201.         print ("[Enter]:step [R]:run [B 0xadr]:add break "
  1202.                    "[M 0xadr]:see RAM [Q]:quit")
  1203.         while True:
  1204.             v = raw_input()
  1205.             if len(v) == 0:
  1206.                 return
  1207.             elif v[0] == 'M':
  1208.                 self.see_ram(machine.state(), int(v[1:], 16))
  1209.             elif v[0] == 'B':
  1210.                 self._breaks.append(int(v[1:], 16))
  1211.             elif v[0] == 'R':
  1212.                 self._run_to_next_state()
  1213.                 return
  1214.             elif v[0] == 'Q':
  1215.                 return
  1216.  
  1217.  
  1218. class PrintStateAndRun(object):
  1219.  
  1220.     def next_state(self):
  1221.         return self
  1222.  
  1223.     def update(self, machine):
  1224.         print
  1225.         print machine.state()
  1226.         print DisAsm().decode_instr(machine.state().instr_bytes())
  1227.         machine.next_clock(None)
  1228.  
  1229. class Runner(object):
  1230.  
  1231.     def __init__(self, initial):
  1232.         self._runner = initial
  1233.  
  1234.     def update(self, machine):
  1235.         self._runner = self._runner.next_state()
  1236.         self._runner.update(machine)
  1237.  
  1238.  
  1239. def main(program_path, debug, debug_step):
  1240.     with open(program_path, 'rb') as program_file:
  1241.         machine = Machine(State(), DisAsm())
  1242.         machine.state().set_reg_value(Register.index_from_name('SP'),
  1243.                                       0x100, True)
  1244.         machine.load(program_file.read())
  1245.         if debug or debug_step:
  1246.             if debug_step:
  1247.                 runner = Runner(InteractiveDebug())
  1248.             elif debug:
  1249.                 runner = Runner(PrintStateAndRun())
  1250.             while not machine.state().halted():
  1251.                 runner.update(machine)
  1252.         else:
  1253.             def run(console, machine):
  1254.                 while (machine.next_clock(console)):
  1255.                     pass
  1256.  
  1257.             import console
  1258.             console.run(run, machine)
  1259.  
  1260.  
  1261. if __name__ == '__main__':
  1262.     import sys
  1263.     main(os.path.join(os.path.dirname(__file__), 'codegolf'),
  1264.          debug=len(sys.argv) > 1,
  1265.          debug_step=len(sys.argv) > 2
  1266.         )
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×