-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassembler.py
175 lines (144 loc) · 5.22 KB
/
assembler.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
"""
Program : CO224 Assembler
Author : Chamath Colombage - E/19/057
Date : 24-April-2024
Description:
This code has been reviewed and tested up to Lab 5 Part 4.
It is not recommended to use this code for any of the subsequent labs, as there may be errors present.
This code is provided as is, without any guarantees of correctness.
Please proceed with caution and use at your own risk.
Note: You must define the op-codes assinged to instructions' opearations, to match the definitions in your instruction set architecture.
Edit the relevant section below.
Usage: python assembler.py <input_file>
or
Usage: py assembler.py <input_file>
OUTPUT: instr_mem.mem file will be created in the same directory as the input file.
"""
import sys
### EDIT BELOW DICTIONARY TO MATCH YOUR DEFINED OPCODES
# Opcode Definitions dictionary
opcodes = {
"loadi": "00000000",
"mov": "00000001",
"add": "00000010",
"sub": "00000011",
"and": "00000100",
"or": "00000101",
"j": "00000110",
"beq": "00000111",
"mult":"00001000",
"bne":"00001001",
"ror":"00001010",
"sra":"00001011",
"sll":"00001100",
"srl":"00001101",
"lwd":"00001110",
"lwi":"00001111",
"swd":"00010000",
"swi":"00010001"
}
def main():
if len(sys.argv) != 2:
print("Usage: python assembler.py <input_file>")
return
input_file = sys.argv[1]
output_file = "instr_mem" + ".mem"
try:
with open(input_file, 'r') as fi, open(output_file, 'w') as fo:
line_num = 0
for line in fi:
# Preprocess the line
line_num = line_num + 1
pline = preprocess_line(line)
# Encode the preprocessed line into machine code
machine_code = encode_instruction(pline,line_num)
# Write machine code to output file
if machine_code == "":
pass
else:
fo.write(machine_code + "\n")
except FileNotFoundError:
print("Error: Input file not found.")
except Exception as e:
print("An error occurred:", e)
def preprocess_line(line):
# Preprocess the line and insert "X" for ignored fields where needed
pline = ""
tokens = line.strip().split()
if tokens[0].startswith("//"):
# print("comment: ",tokens[1:])
pline = ""
else:
for token in tokens:
if token.startswith("//"):
break
else:
pline += token + " "
return pline
def encode_instruction(pline,line_num):
# Encode the preprocessed line of assembly code into machine code
tokens = pline.strip().split()
if len(tokens) == 0:
return ""
else:
instruction = []
if len(tokens) == 3:
instruction.append(get_register_binary(tokens[2]))
if(tokens[0] == "swd" or tokens[0] == "swi"):
instruction.append(get_register_binary(tokens[1]))
instruction.append("00000000")
else:
instruction.append("00000000")
instruction.append(get_register_binary(tokens[1]))
# Finally opcode
try:
instruction.append(get_opcode(tokens[0],line_num))
except IndexError:
print("Error no opcode!!\nI give up!")
exit(1)
else:
try:
if(tokens[0] == "srl"):
temp = "1" + format(int(tokens[3], 16), '07b')
instruction.append(temp)
else:
instruction.append(get_register_binary(tokens[3]))
except IndexError:
instruction.append("00000000")
try:
instruction.append(get_register_binary(tokens[2]))
except IndexError:
instruction.append("00000000")
# Now, RD
try:
instruction.append(get_register_binary(tokens[1]))
except IndexError:
instruction.append("00000000")
# Finally opcode
try:
instruction.append(get_opcode(tokens[0],line_num))
except IndexError:
print("Error no opcode!!\nI give up!")
exit(1)
return " ".join(instruction)
def get_opcode(operation,line_num):
# Get opcode for the given operation from the opcodes dictionary
# If operation is not found, give error
try:
return opcodes[operation]
except KeyError:
print(f"Error: At line {line_num}, \'{operation}\' is not a predefined instruction.")
exit(1)
def get_register_binary(register):
# Get binary representation of register number
if register.isdigit():
# If the input is a decimal value
return format(int(register), '08b')
elif register.startswith("0x") or register.startswith("0X"):
# If the input is a hexadecimal value
return format(int(register, 16), '08b')
else:
# If the input is neither decimal nor hexadecimal
return "00000000"
if __name__ == "__main__":
main()