Guest
Public paste!

phlyingpenguin

By: a guest | Feb 9th, 2010 | Syntax: Python | Size: 5.79 KB | Hits: 28 | Expires: Never
This paste has a previous version, view the difference. Copy text to clipboard
  1. #!/bin/env python
  2.  
  3. """
  4. This is a hypothetical virtual machine. It has two registers and can perform addition, conditionals, and stack operations.
  5.  
  6. example_code.txt:
  7. #########################################
  8. # Iterative  Fibonacci Number Generator #
  9. #########################################
  10. #
  11. 30055 # 00 JMP 55
  12. 00001 # 01 DATA fib-1
  13. 00000 # 02 DATA fib-2
  14. 00020 # 03 DATA 20 (Process until #20)
  15. 00000 # 04 DATA counter
  16. 00001 # 05 DATA 1
  17. 01001 # 06 LDA 01
  18. 50000 # 07 PRI
  19. 01004 # 08 LDA 04 (load counter)
  20. 20005 # 09 ADD 05 (add const 1)
  21. 02004 # 10 STA 04 (save counter)
  22. 03000 # 11 XAB
  23. 01003 # 12 LDA 03
  24. 32023 # 13 JIE 23 (Jump to halt if done)
  25. 01001 # 14 LDA 01 // a = b + c
  26. 20002 # 15 ADD 02
  27. 50000 # 16 PRI
  28. 03000 # 17 XAB // Store A for later
  29. 01001 # 18 LDA 01 // c = b
  30. 02002 # 19 STA 02
  31. 03000 # 20 XAB
  32. 02001 # 21 STA 01 // b = a
  33. 30008 # 22 JMP 08
  34. 99000 # 23 HLT
  35. 00072 # 24 DATA 'H'
  36. 00101 # 25 DATA 'e'
  37. 00108 # 26 DATA 'l'
  38. 00108 # 27 DATA 'l'
  39. 00111 # 28 DATA 'o'
  40. 00032 # 29 DATA ' '
  41. 00087 # 30 DATA 'W'
  42. 00111 # 31 DATA 'o'
  43. 00114 # 32 DATA 'r'
  44. 00108 # 33 DATA 'l'
  45. 00100 # 34 DATA 'd'
  46. 00033 # 35 DATA '!'
  47. 00010 # 36 DATA '\n'
  48. 00014 # 37 DATA 14
  49. 00023 # 38 DATA offset
  50. 00000 # 39 DATA placemarker
  51. 01004 # 40 LDA 04 (load counter)
  52. 20005 # 41 ADD 05 (add const 1)
  53. 02004 # 42 STA 04 (save counter)
  54. 03000 # 43 XAB
  55. 01037 # 44 LDA 37 (12)
  56. 32052 # 45 JIE 52 (Jump to func_end if done)
  57. 01004 # 46 LDA 04 (counter)
  58. 20038 # 47 ADD 38 (add offset)
  59. 02039 # 48 STA 39 (save place)
  60. 05039 # 49 LDP 39 (load place address)
  61. 51000 # 50 PRA
  62. 30040 # 51 JMP 40
  63. 04000 # 52 CLA
  64. 02004 # 53 STA 04
  65. 30057 # 54 JMP 57
  66. 42040 # 55 SAV
  67. 30040 # 56 JMP 40
  68. 43000 # 57 LOD
  69. 30006 # 58 JMP 06
  70. """
  71.  
  72. import sys
  73. import getopt
  74.  
  75. # Mnemonics
  76. NOP = 00 # No op, useful for allowing the machine to skip DATA entries
  77. LDA = 01 # LOAD address into A
  78. STA = 02 # STORE A into address
  79. XAB = 03 # SWAP A & B
  80. CLA = 04 # CLEAR A
  81. LDP = 05 # LOAD the value that Adrress points to
  82. ADD = 20 # ADD address to A
  83. SUB = 21 # SUBTRACT address from A
  84. JMP = 30 # JUMP to address
  85. JLE = 31 # JUMP to address if less-than or equal
  86. JIE = 32 # JUMP to address if equal
  87. JLT = 33 # JUMP to address if less than
  88. PSH = 40 # PUSH A onto stack
  89. POP = 41 # POP off stack into A
  90. SAV = 42 # SAVE A & B (for function jumps)
  91. LOD = 43 # LOAD A & B (for function returns)
  92. PRI = 50 # PRINT contents of A as int
  93. PRA = 51 # PRINT contents of A as char
  94. HLT = 99 # HALT computer
  95.  
  96. debug = False
  97.  
  98. class BadCodeException(Exception):
  99.     def __init__(self, mar, mdr, ir, op, addr):
  100.         self.value = [mar,mdr,ir,op,addr]
  101.     def __str__(self):
  102.         return repr(self.value)
  103.  
  104. def usage():
  105.     print "Usage of the hypothetical computer"
  106.     print
  107.     print "-h, --help\tPrint this message"
  108.     print "-f, --file=\tRead file for code input"
  109.     print "-d, --debug\tShow debug information to stderr"
  110.     print "\t\t  This is best to display using 2> debug.txt"
  111.  
  112. def read_file(file=sys.stdin):
  113.     code = []
  114.     for line in file.readlines():
  115.         line = line.split('#')[0].strip()
  116.         if len(line) > 0:
  117.             code.append(int(line))
  118.     return code
  119.  
  120. def parse_code(memory):
  121.     global debug
  122.     ir, a, b, mdr = 0, 0, 0, 0
  123.     pc, mar, op = 0, 0, 0
  124.     stp = 512
  125.  
  126.     if debug:
  127.         sys.stderr.write("PC\tOP\tAddr\tA\tB\tSTP\tStack\n")
  128.     while True:
  129.         mar = pc
  130.         mdr = memory[mar]
  131.         ir = mdr
  132.  
  133.         op = ir / 1000
  134.         addr = ir % 1000
  135.  
  136.         if debug:
  137.             sys.stderr.write("%s\t%s\t%s\t%s\t%s\t%s\t%s\n" % (pc, op, addr, a, b, stp, memory[stp]))
  138.  
  139.         pc += 1
  140.  
  141.         if op == LDA:
  142.             mar = addr
  143.             mdr = memory[mar]
  144.             a = mdr
  145.         elif op == STA:
  146.             mar = addr
  147.             mdr = a
  148.             memory[mar] = mdr
  149.         elif op == XAB:
  150.             temp = a
  151.             a = b
  152.             b = temp
  153.         elif op == CLA:
  154.             a = 0
  155.         elif op == LDP:
  156.             mar = addr
  157.             mdr = memory[mar]
  158.             a = memory[mdr]
  159.         elif op == ADD:
  160.             mar = addr
  161.             mdr = memory[mar]
  162.             a = a + mdr
  163.         elif op == SUB:
  164.             mar = addr
  165.             mdr = memory[mar]
  166.             a = a - mdr
  167.         elif op == JMP:
  168.             pc = addr
  169.         elif op == PSH:
  170.             stp += 1
  171.             memory[stp] = a
  172.         elif op == POP:
  173.             a = memory[stp]
  174.             stp -= 1
  175.         elif op == SAV:
  176.             memory[stp+1] = a
  177.             memory[stp+2] = b
  178.             stp += 2
  179.         elif op == LOD:
  180.             a = memory[stp-2]
  181.             b = memory[stp-1]
  182.             stp -= 2
  183.         elif op == JLE:
  184.             if a <= b: pc = addr
  185.         elif op == JIE:
  186.             if a == b: pc = addr
  187.         elif op == JLT:
  188.             if a < b: pc = addr
  189.         elif op == PRI:
  190.             print a
  191.         elif op == PRA:
  192.             sys.stdout.write(chr(a))
  193.         elif op == HLT:
  194.             sys.exit(0)
  195.         elif op == NOP:
  196.             continue
  197.         else:
  198.             raise BadCodeException(mar,mdr,ir,op,addr)
  199.  
  200. def main(argv):
  201.     global debug
  202.     memory = [0 for i in xrange(0,1024)]
  203.     file_read = False
  204.     try:
  205.         opts, args = getopt.getopt(argv[1:], "hf:d", ["help", "file=", "debug"])
  206.     except getopt.GetoptError, err:
  207.         sys.stderr.write(str(err))
  208.         usage()
  209.         sys.exit(2)
  210.  
  211.     for opt, arg in opts:
  212.         if opt in ('-f', '--file'):
  213.             code = read_file(open(arg, 'r'))
  214.             file_read = True
  215.         if opt in ('-h', '--help'):
  216.             usage()
  217.             sys.exit(0)
  218.         if opt in ('-d', '--debug'):
  219.             debug = True
  220.     if not file_read:
  221.         code = read_file()
  222.     memory = code + memory
  223.     parse_code(memory[0:1024])
  224.  
  225. if __name__ == '__main__': main(sys.argv)