-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathasm.py
More file actions
executable file
·136 lines (117 loc) · 3.21 KB
/
Copy pathasm.py
File metadata and controls
executable file
·136 lines (117 loc) · 3.21 KB
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
#!/usr/bin/env python3
import re
import sys
# Get the input assembly program filename from command line arguments
progf = sys.argv[1]
# Dictionary mapping assembly instructions to their opcodes
inst = {
"nop": 0x00,
"call": 0b00000001,
"ret": 0b00000010,
"lda": 0b10000111,
"out": 0b00000011,
"in": 0b00000100,
"hlt": 0b00000101,
"cmp": 0b00000110,
"sta": 0b10111000,
"jmp": 0b00011000,
"jz": 0b00011001,
"jnz": 0b00011010,
"je": 0b00011001,
"jne": 0b00011010,
"jc": 0b00011011,
"jnc": 0b00011100,
"push": 0b00100000,
"pop": 0b00101000,
"add": 0b01000000,
"sub": 0b01001000,
"inc": 0b01010000,
"dec": 0b01011000,
"and": 0b01100000,
"or": 0b01101000,
"xor": 0b01110000,
"adc": 0b01111000,
"ldi": 0b00010000,
"mov": 0b10000000,
}
# Register mapping to 3-bit codes
reg = {
"A": 0b000,
"B": 0b001,
"C": 0b010,
"D": 0b011,
"E": 0b100,
"F": 0b101,
"G": 0b110,
"M": 0b111,
}
# Section constants
TEXT, DATA = 0, 1
# Memory size (256 bytes)
MEM_SIZE = 256
mem = [0 for _ in range(MEM_SIZE)]
cnt = 0
labels = {}
data = {}
data_addr = {}
# Helper function to parse integers in decimal, hex (0x), or binary (0b)
def rich_int(v):
if v.startswith("0x"):
return int(v, 16)
elif v.startswith("0b"):
return int(v, 2)
else:
return int(v)
with open(progf) as f:
for l in f:
l = re.sub(";.*", "", l)
l = l.strip()
if l == "":
continue
if l == ".text":
section = TEXT
elif l == ".data":
section = DATA
else:
if section == DATA:
n, v = list(map(str.strip, l.split("=", 2)))
data[str(n)] = int(v)
elif section == TEXT:
kw = l.split()
if kw[0][-1] == ":":
labels[kw[0].rstrip(":")] = cnt
else:
current_inst = kw[0]
if current_inst == "ldi":
r = reg[kw[1]]
kw[0] = (inst[kw[0]] & 0b11111000) | r
del kw[1]
kw[1] = rich_int(kw[1])
elif current_inst in ("push", "pop"):
r = reg[kw[1]]
kw[0] = (inst[kw[0]] & 0b11111000) | r
del kw[1]
elif current_inst == "mov":
op1 = reg[kw[1]]
op2 = reg[kw[2]]
kw[0] = (inst[kw[0]] & 0b11111000) | op2
kw[0] = (kw[0] & 0b11000111) | (op1 << 3)
del kw[2]
del kw[1]
else:
kw[0] = inst[kw[0]]
for a in kw:
mem[cnt] = a
cnt += 1
data = dict(sorted(data.items()))
# Write data into memory
for k, v in list(data.items()):
data_addr[k] = cnt
mem[cnt] = v
cnt += 1
data_addr.update(labels)
# Replace variables
for i, b in enumerate(mem):
if str(b).startswith("%"):
mem[i] = data_addr[b.lstrip("%")]
print(' '.join(['%02x' % int(b) for b in mem]))