-
Notifications
You must be signed in to change notification settings - Fork 0
/
pseudo-assembly.py
159 lines (134 loc) · 4.94 KB
/
pseudo-assembly.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import sys
# ---------------------------------------------------- #
CODE = [None]
PROGRAM_COUNTER = 1
ACCUMULATOR = None
MEMORY = dict()
OPCODES = { "READ": lambda : read(),
"WRITE": lambda : write(),
"ADD": lambda x: math(x, '+'),
"SUB": lambda x: math(x, '-'),
"MULT": lambda x: math(x, '*'),
"DIV": lambda x: math(x, '/'),
"ADD=": lambda x: explicit_math(x, '+'),
"SUB=": lambda x: explicit_math(x, '-'),
"MULT=": lambda x: explicit_math(x, '*'),
"DIV=": lambda x: explicit_math(x, '/'),
"ADD@": lambda x: indirect_math(x, '+'),
"SUB@": lambda x: indirect_math(x, '-'),
"MULT@": lambda x: indirect_math(x, '*'),
"DIV@": lambda x: indirect_math(x, '/'),
"LOAD": lambda x: load(x),
"LOAD=": lambda x: explicit_load(x),
"LOAD@": lambda x: indirect_load(x),
"STORE": lambda x: store(x),
"STORE@": lambda x: indirect_store(x),
"BR": lambda x: branch(x, ''),
"BEQ": lambda x: branch(x, '=='),
"BNE": lambda x: branch(x, '!='),
"BL": lambda x: branch(x, '<'),
"BLE": lambda x: branch(x, '<='),
"BG": lambda x: branch(x, '>'),
"BGE": lambda x: branch(x, '>='),
"END": lambda : end()
}
# ---------------------------------------------------- #
def read():
global ACCUMULATOR
try:
ACCUMULATOR = int(input())
except ValueError:
error("Input must be an integer")
def write():
if ACCUMULATOR == None:
error("Undefined accumulator")
print(ACCUMULATOR)
def math(param, op):
global ACCUMULATOR
try:
if param[0] == '=': value = int(param[1:])
elif param[0] == '@': value = MEMORY[MEMORY[int(param[1:])]]
else: value = MEMORY[int(param)]
if op == '+': ACCUMULATOR += value
elif op == '-': ACCUMULATOR -= value
elif op == '*': ACCUMULATOR *= value
elif op == '/': ACCUMULATOR /= value
except ValueError:
error("Parameter must be an integer")
except TypeError:
error("Undefined accumulator")
except KeyError:
error("Undefined memory location")
except ZeroDivisionError:
error("Division by zero")
def explicit_math(param, op):
math('=' + param, op)
def indirect_math(param, op):
math('@' + param, op)
def load(param):
global ACCUMULATOR
try:
if param[0] == '=': ACCUMULATOR = int(param[1:])
elif param[0] == '@': ACCUMULATOR = MEMORY[MEMORY[int(param[1:])]]
else: ACCUMULATOR = MEMORY[int(param)]
except ValueError:
error("Parameter must be an integer")
except KeyError:
error("Undefined memory location")
def explicit_load(param):
load('=' + param)
def indirect_load(param):
load('@' + param)
def store(param):
global MEMORY
try:
if param[0] == '@': MEMORY[MEMORY[int(param[1:])]] = ACCUMULATOR
else: MEMORY[int(param)] = ACCUMULATOR
except ValueError:
error("Parameter must be an integer")
except TypeError:
error("Undefined accumulator")
def indirect_store(param):
store('@' + param)
def branch(param, cond):
global PROGRAM_COUNTER
try:
target = int(param)-1
# program_counter is automatically incremented by the main loop
if target < 0 or target >= len(CODE)-1:
error("Branch to undefined instruction")
if cond == '' or \
cond == '==' and ACCUMULATOR == 0 or \
cond == '!=' and ACCUMULATOR != 0 or \
cond == '<' and ACCUMULATOR < 0 or \
cond == '<=' and ACCUMULATOR <= 0 or \
cond == '>' and ACCUMULATOR > 0 or \
cond == '>=' and ACCUMULATOR >= 0:
PROGRAM_COUNTER = target
except ValueError:
error("Parameter must be an integer")
def end():
exit()
def error(msg):
print("ERROR AT LINE {0} - {1}".format(PROGRAM_COUNTER, msg))
exit()
def execute(instruction):
try:
parameters = instruction.split()
opcode = parameters[0].upper()
if len(parameters) == 2:
OPCODES[opcode](parameters[1])
else:
OPCODES[opcode]()
except TypeError:
error("Wrong number of parameters")
# ---------------------------------------------------- #
if len(sys.argv) < 2:
print("Specify the file to execute as parameter")
exit()
with open(sys.argv[1]) as program:
CODE.extend(program.readlines())
while PROGRAM_COUNTER > 0 and PROGRAM_COUNTER < len(CODE):
instruction = CODE[PROGRAM_COUNTER]
execute(instruction)
PROGRAM_COUNTER += 1