forked from AlphaKure/SIC-Assembler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
classVer.py
220 lines (206 loc) · 9.46 KB
/
classVer.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
class assembler:
'''
參數:
locationList:存各指令在記憶體位置
programName:存程式名稱
startLocation:存程式起始位置
symbolTable:存本程式所有指令名稱
machineCode:存本程式所有指令機器碼
opcodeTable:存opcode值dict
inputFile:來源檔案位址
locFile:輸出loc.txt位置
outputFile:輸出output.txt位置
objectcodeFile:輸出objectcode.txt位置
方法:
calHex:處理16進制轉換等功能
memoryLocationCal:計算各指令占用記憶體大小
machineCodeGenerator:處理指令轉機器碼
createObjectProgram:處理並生成objectcode.txt
process:主執行程式
'''
def __init__(self,inputFile:str,outputFile='./output.txt',locFile='./loc.txt',objectcodeFile='./objectcode.txt') -> None:
'''
inputFile:來源檔案位址(必填!!!!)
locFile:輸出loc.txt位置
outputFile:輸出output.txt位置
objectcodeFile:輸出objectcode.txt位置
'''
self.locationList=list()
self.programName=""
self.startLocation=""
self.symbolTable=dict()
self.machineCode=list()
self.opcodeTable={"ADD":"18","AND":"40","COMP":"28","DIV":"24","J":"3C","JEQ":"30","JGT":"34","JLT":"38","JSUB":"48","LDA":"00","LDCH":"50","LDL":"08","LDX":"04","MUL":"20","OR":"44","RD":"D8","RSUB":"4C","STA":"0C","STCH":"54","STL":"14","STSW":"E8","STX":"10","SUB":"1C","TD":"E0","TIX":"2C","WD":"DC"}
self.inputFile=open(inputFile,'r',encoding='utf-8')
self.outputFile=open(outputFile,'w',encoding='utf-8')
self.locFile=open(locFile,'w',encoding='utf-8')
self.objectcodeFile=open(objectcodeFile,'w',encoding='utf-8')
def calHex(self,strHex:str=None,intDec:int=None,bits:int=4)->str:
'''
輸入參數:
1.strHex:16進制字串,預設為None
2.intDec:10進制整數,預設為None
3.bits:轉出位元數,預設為4
輸出:
你所設定的幾bits16進制字串
ex: strHex=1,bits=4 ->'0001'
功能:
1.只輸入strHex和bits:
>執行擴充位元
2.輸入strHex和intDec(bits選填):
>執行16進制加法
3.只輸入intDec(bits選填):
>執行10進制轉16進制
'''
if strHex!=None:
if intDec!=None:
# 16進制+10進制
return self.calHex(intDec=(int(strHex,16)+intDec),bits=bits)
else:
# 擴充位元
while len(strHex)<bits:
strHex='0'+strHex
return strHex.upper()
if intDec!=None:
# 10進制轉16進制
temp=hex(intDec)[2:] # 拔除基底
while len(temp)<bits:
temp='0'+temp
return temp.upper()
def memoryLocationCal(self,chunk:list[str])->int:
'''
輸入:
chunk:每行組合語言指令
輸出:
其指令大小
ex: chunk=['AAA','RESB','69'] -> 69
'''
if chunk[1]=='RESW': # RESW需留大小*3
return int(chunk[2])*3
elif chunk[1]=='RESB':
return int(chunk[2]) # RESB需留大小*1
elif chunk[1]=='BYTE':
if chunk[2].startswith('C'): # BYTE中C為char 需佔用C''內字元數*2(ASCII)
return len(chunk[2].split("'")[1])
elif chunk[2].startswith('X'): # BYTE中X為Hex 需佔用X''內值字元數*1
return int(len(chunk[2].split("'")[1])/2)
else:
return 3 # 其他指令皆佔3位元(START END等不佔空間指令會在其他程式中忽略)
def machineCodeGenerator(self,chunk:list[str])->str:
'''
輸入:
chunk:每行組合語言指令
輸出:
輸出每行組語轉機器碼
'''
nullObjectList={'START','END','RESW','RESB'} # 沒有機器碼的指令 輸出空字串
if chunk[0]!='.': #非註解行
if chunk[1] in nullObjectList:
return ''
else:
if chunk[1]!='BYTE' and chunk[1]!='WORD':
# case1: 非BYTE非WORD
if len(chunk)==2:
# 沒有TargetAddress
return self.opcodeTable[chunk[1]]+'0000'
elif chunk[2] and not chunk[2].endswith(',X'):
# 不使用索引定值
return self.opcodeTable[chunk[1]]+self.symbolTable[chunk[2]]
else:
# 使用索引定值,即TA,X
temp=self.calHex(strHex=self.opcodeTable[chunk[1]]+self.symbolTable[chunk[2].split(',')[0]],intDec=32768,bits=6)
return temp
else:
if chunk[1]=='WORD':
# case2: WORD
return self.calHex(strHex=hex(int(chunk[2]))[2:],bits=6)
elif chunk[1]=='BYTE' and chunk[2].startswith('C'):
# case3: BYTE 內容為char
asc=[hex(ord(char))[2:] for char in chunk[2].split("'")[1]] #轉ASCII 1.先拉出每個字元 2.用ord()將各字元轉ascii數值 3. 將數值轉為16進制
temp=""
for code in asc:
temp=temp+code
return temp.upper()
elif chunk[1]=='BYTE' and chunk[2].startswith('X'):
# case4: BYTE 內容為hex
return chunk[2].split("'")[1].upper()
else: # 註解行 不執行轉換
return None
def createObjectProgram(self)->None:
'''
功能:
處理並生成objectcode.txt
'''
while len(self.programName)<6: # 擴充程式名稱
self.programName=self.programName+' '
self.objectcodeFile.write(f'H{self.programName}{self.startLocation}{self.calHex(intDec=int(self.locationList[-1],16)-int(self.startLocation,16),bits=6)}\n')
iter=0
temp=''
loc=self.startLocation
for code in self.machineCode:
if code==None:
pass # 註解行跳過
elif code=='': # 因RESW RESB START END 而造成的跳行
if temp!='': # 避免因 START END 或連續RES temp為空輸出
self.objectcodeFile.write(f'T{loc}{self.calHex(intDec=len(temp)//2,bits=2)}{temp}\n')
temp=''
if iter!=len(self.machineCode)-1: #避免超出範圍報錯
loc=self.calHex(strHex=self.locationList[iter+1],bits=6)
else:
if len(temp+code)>60: #檢查接下來加入項會不會超過範圍
self.objectcodeFile.write(f'T{loc}{self.calHex(intDec=len(temp)//2,bits=2)}{temp}\n')
temp=''
loc=self.calHex(strHex=self.locationList[iter],bits=6)
temp=temp+code
iter+=1
self.objectcodeFile.write(f'E{self.startLocation}\n')
self.objectcodeFile.close()
def process(self):
'''
主執行程式
'''
asmData=self.inputFile.readlines()
asm=list() # 每行指令分割list
for data in asmData:
if len(data.strip().split())<3: #有三種可能 1.註解行 2.沒有symbol的指令 3.沒有TA的指令(不太影響啦)
# 把沒有設定symbol的指令加上'-' 使所有指令分割list長度都為3
if data.strip().split()[0]!='.':
data='-'+data
asm.append(data.strip().split())
for chunk in asm: # 計算指令位址
if chunk[0]!='.':# 非註解
if chunk[1]=='START':
# 第一行
self.programName=chunk[0]
self.startLocation=self.calHex(strHex=chunk[2],bits=6)
nowLocation=self.calHex(strHex=chunk[2],bits=4)
self.locationList.append(nowLocation)
else:
# 其他行
self.locationList.append(nowLocation)
if chunk[0]!='-':
self.symbolTable[chunk[0]]=nowLocation #找出所有symbol 將symbol位址存入symbolTable
nowLocation=self.calHex(strHex=nowLocation,intDec=self.memoryLocationCal(chunk))
else:
self.locationList.append(nowLocation)
#生成機器碼 不能與上合併原因是symbol可能在下面
for chunk in asm:
self.machineCode.append(self.machineCodeGenerator(chunk))
#輸出loc.txt和output.txt
iter=0
for line in asmData:
if self.machineCode[iter]!=None: # 不輸出註解行
self.outputFile.writelines(f'{self.locationList[iter]} {line.rstrip()} {self.machineCode[iter]} \n')
self.locFile.writelines(f'{self.locationList[iter]} {line} ')
iter+=1
self.outputFile.close()
self.locFile.close()
#輸出及生成objectcode.txt
self.createObjectProgram()
if __name__=='__main__':
a=assembler('./testdata/monday.txt'
,outputFile='./output/output.txt'
,locFile='./output/loc.txt'
,objectcodeFile='./output/objectcode.txt'
)
a.process()