# emu8086.py

Feb 26th, 2012
2,608
0
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.
60.         return self._m[start:start + length]
61.
64.
66.         return self._m[pos]
67.
68.     def hexdump(self, 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
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.
110.         if is_word:
112.         else:
114.
115.     def write_ram(self, start, value, is_word):
116.         raise NotImplementedError
117.
118.     def ram(self, start, length):
120.
121.     def instr_bytes(self):
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.
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.
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.
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
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()
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.
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.
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:
374.         elif self._reg2 is None:
376.         else:
378.
380.         return '' if self._disp == 0 else ' + {0}'.format(hex(self._disp))
381.
382.
384.     def __str__(self):
385.         return '[({0}) + ({1}){2}]'.format(self._reg1,
386.                                            self._reg2,
388.                                           )
389.
391.         return (machine_state.reg_value(self._reg1.index()) +
392.                 machine_state.reg_value(self._reg2.index()) +
393.                 self._disp
394.                 )
395.
396.
398.     def __str__(self):
400.
402.         return machine_state.reg_value(self._reg1.index()) + self._disp
403.
404.
406.     def __str__(self):
407.         return '[{0}]'.format(hex(self._disp))
408.
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.
457.         result = machine_state.reg_value(self._reg.index()) + self._im
458.         machine_state.set_reg_value(self._reg.index(), 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.
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)
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.
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)
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(
588.            self._im,
589.            self._word,
590.            machine_state
591.           )
592.
593.
599.
600.     def exec_or(self, machine_state):
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(
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(
626.                                 machine_state.reg_value(self._reg.index()),
627.                                 self._word
628.                                )
629.
630.     def exec_and(self, machine_state):
633.                   machine_state.reg_value(self._reg.index())
634.                   )
636.         machine_state.set_flags_from_logical_result(result, self._word)
637.
641.                   machine_state.reg_value(self._reg.index())
642.                   )
645.
646.
647.     def exec_sub(self, machine_state):
648.         machine_state.write_ram(
650.                 sub_upd_flags(
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(),
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():
756.
757.     def exec_jc(self, machine_state):
758.         if machine_state.cf():
760.
761.     def exec_jnz(self, machine_state):
762.         if not machine_state.zf():
764.
765.     def exec_jnbe(self, machine_state):
766.         if not machine_state.zf() and not machine_state.cf():
768.
769.     def exec_jns(self, machine_state):
770.         if not machine_state.sf():
772.
773.     def exec_jbe(self, machine_state):
774.         if machine_state.cf() or machine_state.zf():
776.
777.     def exec_jmp(self, machine_state):
779.
780.
781.     def exec_call(self, machine_state):
782.         machine_state.push_stack(machine_state.ip())
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
790.
793.
794.     def __str__(self):
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':
927.             else:
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.
1184.         print "M {0}: {1} ...".format(
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)
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)
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.         )