-
Notifications
You must be signed in to change notification settings - Fork 0
/
pass1.py
179 lines (159 loc) · 5.3 KB
/
pass1.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
176
177
178
179
#PASS-1 of the SIC-XE assemler. Takes the whole program as input and assigns adress to each line and assigns machine code to all OPCODEs in the program
#Uses OPTAB for fetching machine code of the opcode and length and type of the opcode.
#Uses SYMTAB for storing symbols and their addresses, values and length.
#Writes the intermediate file.
import re
import sys
import pass2
#Global Declaration.
SYMTAB={}
OPTAB={'ADD':'18','ADDF':'58','ADDR':'90','AND':'40','CLEAR':'B4','COMP':'28','COMPF':'88','COMPR':'A0','DIV':'24','DIVF':'64','DIVR':'9C','FIX':'C4','FLOAT':'C0','HIO':'F4','J':'3C','JEQ':'30','JGT':'34','JLT':'38','JSUB':'48','LDA':'00','LDB':'68','LDCH':'50','LDF':'70','LDL':'08','LDS':'6C','LDT':'74','LDX':'04','LPS':'D0','MULF':'60','MULR':'98','NORM':'C8','OR':'44','RD':'D8','RMO':'AC','RSUB':'4C','SHIFTL':'A4','SHIFTR':'A8','SIO':'F0','SSK':'EC','STA':'0C','STB':'78','STCH':'54','STF':'80','STI':'D4','STL':'14','STS':'7C','STSW':'E8','STT':'84','STX':'10','SUB':'1C','SUBF':'5C','SUBR':'94','SVC':'B0','TD':'E0','TIO':'F8','TIX':'2C','TIXR':'B8','WD':'DC'}
LOCTR=0
prog=[]
st_ads=0
#The 'checkSYMTAB()' function. checks if a symbol is present in the Global SYMTAB.
#If already present returns error. else inserts symbol and its address to SYMTAB.
def checkSYMTAB(symbol,opcode,operator):
global LOCTR
global SYMTAB
#Check if the symbol is already present in SYMTAB. If present duplicate symbol error.
if symbol in SYMTAB:
return 1
else:
val=[]
length=-1
if opcode=='RESW':
#Get the value and length to store in SYMTAB.
try:length=3*int(operator)
except:return 2
val.append('')
elif opcode=='RESB':
#get the value and length to store in SYMTAB.
try:length=int(operator)
except:return 2
val.append('')
elif opcode=='WORD':
#Get the value and length to store in SYMTAB.
values=operator.split(',')
length=3*len(values)
for values in values:
val.append(values)
#Yet to check for right syntax (num,num,num)
elif opcode=='BYTE':
#Get the value and length to store in SYMTAB.
values=operator.split(',')
length=len(values)
for value in values:
val.append(value)
#Yet to check for right syntax (num,num,num)
#Insert (symbol,LOCTR,values,length) into SYMTAB.
SYMTAB[symbol]=hex(LOCTR)[2:]
return length+10
#THE checkOPTAB() function. Checks whether an opcode is valid or invalid. Returs machine_code and length of the insruction if opcoe is valid.
def checkOPCODE(opcode,operand):
global OPTAB
a=[0,0,'',0]
#If opcode is not in OPTAB it's an invalid ocpode.
if opcode.strip('+') not in OPTAB:
a[0]=1
else:
a[2]=OPTAB[opcode.strip('+')]
if '+' in opcode: #10 is added to avoid confusin between length and error(1)
a[1]=4+10
a[3]=4 #type 4
elif len(operand)==0:
a[1]=1+10
a[3]=1 #type 1
elif operand.split(',')[0] in 'BSTFAXL':
a[1]=2+10
a[3]=2 #typ2
else:
a[1]=3+10
a[3]=3 #type 3
return a
#Strucure of the pass-1 of the assembler. Goes through the program line by line, assigning addresses and putting symbols into SYMYAB.
def pass1(program):
f1=open('intermediate','w')
global LOCTR
global prog
global st_ads
st_ads=0
lineno=1
opflag=[0,0,'',0]
for line in program:
mccode=''
length=0
ins=re.split('[ \n]',line)
if ins[1]=='START':
try:st_ads=int(ins[2].strip('H'))
except:print('Syntax error at line no-'+str(lineno))
LOCTR=st_ads
elif ins[1]!='END' and ins[1]!='BASE':
#If label field is not empty,check in SYMTAB.
if ins[0]!='':
symflag=checkSYMTAB(ins[0],ins[1],ins[2])
if symflag==1:
#DIspaly error(Duplicate symbol)
print("Error:Duplicate Symbol-"+ins[0])
continue
elif symflag==2:
#display error(Invalid Operand)
print("Invalid Operand-"+ins[2])
continue
else:
length=symflag-10
#Check for OPCODE.
opflag=checkOPCODE(ins[1],ins[2])
if opflag[0]==1:
#Check for RESW, RESB, WORD or byte.
if ins[1]=='RESW' or ins[1]=='RESB' or ins[1]=='WORD' or ins[1]=='BYTE':
kfkjfkdh=0
#Do nothing. It would've been handled by 'checkSYMTAB()'.
else:
#Display error mesage(Invalid OPCODE).
print("Error:Invalid OPCODE-"+ins[1])
else:
length=opflag[1]-10
mccode=opflag[2]
#Write the intermediate file.
f1.write(str(hex(LOCTR)[2:])+'\t'+ins[0]+'\t'+ins[1]+'\t'+ins[2]+'\t'+str(mccode)+'\t'+str(length)+'\n')
prog.append([str(hex(LOCTR))[2:],ins[0],ins[1],ins[2],mccode,opflag[3]])
#(Format:address label opcode oprerands machinecode_of_OPCODE length). and store the same thing in something for PASS-2.
LOCTR+=length
lineno+=1
def writeObject(string,f,name,length,st):
#Prepare the header and write to object file.
st=name+'^'+str(st)+'^'+str(length)[2:]+'\n'
f.write(st)
string=string.split('|')
for i in range(99999):
try:string.remove('')
except:break
st=''
count=0
for item in string:
if count<=60:
st+=str(item)+'^'
count+=len(item)
else:
s='T^'+str(hex(count)[2:4])+st
s=s.strip('^')
s+='\n'
f.write(s)
st=''
count=0
def main():
f=open(sys.argv[1],'r')
pass1(f)
global SYMTAB
global st_ads
f2=open('symtab','w')
#print SYMTAB
#print prog
string=pass2.pass2(prog,SYMTAB)
output=open("objectfile2",'w')
#print type(LOCTR),type(st_ads)
writeObject(string,output,sys.argv[1],hex(LOCTR-st_ads),st_ads)
for key in SYMTAB:
f2.write(key+'\t'+str(SYMTAB[key])+'\n')
main()