Need a unique gift idea?
A Pastebin account makes a great Christmas gift
SHARE
TWEET

emu8086.py

j-a Feb 26th, 2012 1,626 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  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
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top