-
-
Save sencagri/882256222422425dbc8d7c13b3ef1031 to your computer and use it in GitHub Desktop.
assembler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import os | |
from instructionSet import instructionSet | |
# program counter | |
pc = 100 | |
# jump list | |
colonList = list() | |
# var list | |
varList = list() | |
# param list | |
param = list() | |
# result list | |
output = list() | |
varOutput = list() | |
# delimiter characters used for splitting line | |
delimiter = "(,)|( )" | |
# global değişken olan program counter değerini fonksiyonlar içersinde arttırmak için kullanılan fonksiyon | |
def incrementPC(): | |
global pc | |
pc = pc + 4 | |
# verilen sayıyı istenilen bit genişliğinde ikinin complementi şekline getiren fonksiyon | |
def to_twoscomplement(bits, value): | |
value = int(value) | |
if value < 0: | |
value = ( 1<<bits ) + value | |
formatstring = '{:0%ib}' % bits | |
return formatstring.format(value) | |
def decodeParameters(stringPart): | |
# split edimiş instruction içerisinde instruction harici item ler üzerinde gez | |
for par in stringPart[1:]: | |
# register value | |
par = par.rstrip() | |
# R veya immediate value değerini al | |
if str.startswith(par, "R") or str.startswith(par, "#"): | |
paramDigit = par[1:]; | |
param.append(paramDigit) | |
continue | |
# eğer ldr veya str gibi memory operasyonları yapacak ise köşeli parantezlerden parse yap | |
if str.startswith(par, "["): | |
pb = str.find(par, "[") + len("[") | |
par = par[pb:] | |
if str.startswith(par, "R"): | |
pb = str.find(par, "R") + 1 | |
par = par[pb:] | |
param.append(par) | |
continue | |
if str.endswith(par, "]"): | |
pe = str.find(par, "]") | |
par = par[:pe] | |
findVar = [item for item in varList if item[0] == par] | |
if len(findVar) > 0: | |
findVar = findVar[0] | |
pcOfVar = findVar[1] | |
param.append(pcOfVar) | |
continue | |
# parametre bir jump list içeriyor mu kontrol et | |
isVar = [item for item in colonList if item[0] == par] | |
if len(isVar) > 0: | |
# this is a 1 parameter instruction | |
isVar = isVar[0][1] | |
param.append(isVar) | |
def extractVars_asm2bin(inData): | |
global pc | |
prevLine = inData[0] | |
globalname = "" | |
globalFound = False | |
colonFound = False | |
# tüm satırları gezmeye başla | |
for line in inData: | |
line = str(line) | |
# halen uzunluğu 0 olan satır varsa pas geç | |
if len(line.strip()) == 0: | |
continue | |
# eğer satır comment satırı ise pas geç | |
if line[0] == ";": | |
continue | |
# programın başlayacağı nokta globalname değişkeninin içerisinde tutuluyor eğer bulunur ise program counter arttırılmayacak | |
if str.find(line,globalname): | |
globalFound = True | |
# global başlama noktası mı diye kontrol et | |
if str.find(line, ".global") > -1: | |
posg = str.index(line, ".global") + len(".global") | |
globalname = line[posg:] | |
# eğer satır değişken tanıtılmak için kullanılmış ise prevLine değişkeninin içersinde hangi değişken olduğunun değeri tutuluyor oradan değişken adını al | |
# program counter değerini de yanına koy varlist listesinin içine append et | |
# ek olarak birden fazla değer memory ye eklenmiş olabileceğinden kaç tane eklenmiş ise program counter değerini o kadar arttır | |
if str.find(line, ".word") > -1: | |
pos = str.index(prevLine, ":") | |
varName = prevLine[:pos] | |
varList.append([varName, pc]) | |
pos =str.find(line, ".word") + len(".word") | |
values = line[pos:] | |
values = str.replace(values, "\n", "") | |
values = re.split(", | ", values) | |
values = list(filter(None, values)) | |
values = list(values) | |
for val in values: | |
varOutput.append(to_twoscomplement(32, int(val)) + os.linesep) | |
lenVal = len(values) -1 | |
pc += lenVal*4 | |
# eğer sıçrama noktası bulundu ise colonlist listesine ekle | |
if str.find(line, ":") > -1: | |
pos = str.find(line, ":") | |
colName = line[:pos] | |
colonList.append([colName, pc]) | |
# colon buldu ise program counter değerini arttırma çünkü bir instruction değil | |
if str.find(line, ":") > -1: | |
colonFound = True | |
if globalFound and colonFound == False and str.find(line, globalname) == -1: | |
incrementPC() | |
colonFound = False | |
prevLine = line | |
# tüm işlemler bittiğinde program counter değerini tekrardan 100 yap | |
pc = 100 | |
def dec_asm2bin(inData): | |
for line in inData: | |
processLine_asm2bin(line) | |
def b_br_ins(insBinary): | |
par = to_twoscomplement(26, param[0]) | |
return insBinary.replace("mmmmmmmmmmmmmmmmmmmmmmmmmm", par) | |
def com_ins(insBinary): | |
val = int(param[1]) - pc -4 | |
par = to_twoscomplement(19,val) | |
insBinary = insBinary.replace("mmmmmmmmmmmmmmmmmmm", par) | |
par = param[0] | |
par = to_twoscomplement(5, par) | |
insBinary = insBinary.replace("nnnnn",par) | |
return insBinary | |
def addi_addiu_ins(insBinary): | |
par = to_twoscomplement(5,param[0]) | |
insBinary = insBinary.replace("nnnnn", par) | |
par = to_twoscomplement(5,param[1]) | |
insBinary = insBinary.replace("mmmmm", par) | |
par = to_twoscomplement(12,param[2]) | |
insBinary = insBinary.replace("dddddddddddd", par) | |
return insBinary | |
def cmp_ins(insBinary): | |
par = to_twoscomplement(5, param[0]) | |
insBinary = insBinary.replace("nnnnn", par) | |
par = to_twoscomplement(6, param[1]) | |
insBinary = insBinary.replace("dddddd", par) | |
return insBinary | |
def ldr_str_ins(insBinary): | |
par = to_twoscomplement(12, param[2]) | |
insBinary = insBinary.replace("mmmmmmmmmmmm", par) | |
par = to_twoscomplement(5, param[1]) | |
insBinary = insBinary.replace("nnnnn", par) | |
par = to_twoscomplement(5, param[0]) | |
insBinary = insBinary.replace("ddddd", par) | |
return insBinary | |
def three_ins(insBinary): | |
par = to_twoscomplement(5, param[1]) | |
insBinary = insBinary.replace("nnnnn", par) | |
par = to_twoscomplement(5, param[0]) | |
insBinary = insBinary.replace("mmmmm", par) | |
par = to_twoscomplement(5, param[2]) | |
insBinary = insBinary.replace("ddddd", par) | |
return insBinary | |
def str_ins(insBinary): | |
par = to_twoscomplement(5, param[0]) | |
insBinary = insBinary.replace("mmmmm", par) | |
par = to_twoscomplement(5, param[1]) | |
insBinary = insBinary.replace("nnnnn", par) | |
return insBinary | |
def putParams(insName, insBinary): | |
# buradaki tüm fonksiyonlar alınan parametreleri yerine koyuyor | |
if insName == "B" or insName == "BR": | |
insBinary = b_br_ins(insBinary) | |
elif insName == "EQ" or insName == "NE" or insName == "GE" or insName == "GT" or insName == "LE" or insName =="LT": | |
insBinary = com_ins(insBinary) | |
elif insName == "ADDI" or insName == "ADDIU": | |
insBinary = addi_addiu_ins(insBinary) | |
elif insName == "CMP": | |
insBinary = cmp_ins(insBinary) | |
elif insName == "LDR" or insName == "STR": | |
insBinary = ldr_str_ins(insBinary) | |
elif insName == "STR": | |
insBinary = str_ins(insBinary) | |
else: | |
insBinary = three_ins(insBinary) | |
return insBinary | |
def processLine_asm2bin(line): | |
endPos = len(line) | |
if endPos > 0: | |
# check if comment added | |
commentIndex = str.find(line, ";") | |
if commentIndex > -1: | |
endPos = commentIndex | |
# copy only to the semicolon pos | |
stringPart = line[:endPos] | |
if len(stringPart) > 0: | |
# check if line is jump point, if so add colonName to list then exit | |
colonIndex = str.find(stringPart, ":") | |
if colonIndex > 0: | |
colonName = stringPart[:colonIndex] | |
#colonList.append([colonName, pc]) | |
return | |
# split by delimiter character | |
stringPart = stringPart.replace("\n", "") | |
#stringPart = [s.strip(',') for s in stringPart] | |
stringPart = re.split(delimiter, stringPart) | |
stringPart = list(filter(None, stringPart)) | |
# search first string in instruction list | |
candidateInst = stringPart[0] | |
candidateRes = [item for item in instructionSet if item[0] == candidateInst] | |
# we found the instruction | |
if len(candidateRes) > 0: | |
insBinary = candidateRes[0][1] | |
insName = candidateRes[0][0] | |
paramSize = 0; | |
decodeParameters(stringPart) | |
if len(param) > 0: | |
insBinary = putParams(insName, insBinary) | |
param.clear() | |
incrementPC() | |
output.append(insBinary + os.linesep) | |
# programın başlangıç noktası indata parametresi ile kullanıcının yazdığı veriler geliyor, | |
def runAssembler(inData): | |
# gelen veriyi satır satır hale getir | |
inData = inData.splitlines() | |
# satırlar arsında boşluk var ise temizle | |
inData = list(filter(None, inData)) | |
extractVars_asm2bin(inData) | |
# decode etme işlemine başla | |
dec_asm2bin(inData) | |
return output + varOutput |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment