Assembler erweitert
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
0000000000000000
|
||||
1111111111111111
|
||||
0000000000010111
|
||||
1111111111111111
|
||||
0000000000010000
|
||||
1111111111111111
|
||||
0100000000000000
|
||||
1111111111111111
|
||||
0000000000010001
|
||||
1111111111111111
|
||||
0000000000010001
|
||||
1111111111111111
|
||||
1111111111111111
|
||||
0000000000010001
|
||||
1111111111111111
|
||||
0000000000100000
|
||||
1111111111111111
|
||||
0000000000010001
|
||||
1111111111111111
|
||||
0000000000010000
|
||||
1111111111111111
|
||||
0000000000001010
|
||||
1111111111111111
|
||||
0000000000010111
|
||||
1111111111111111
|
||||
|
||||
25
asm/Rect2.hack
Normal file
25
asm/Rect2.hack
Normal file
@@ -0,0 +1,25 @@
|
||||
0000000000000000
|
||||
1111110000010000
|
||||
0000000000010111
|
||||
1110001100000110
|
||||
0000000000010000
|
||||
1110001100001000
|
||||
0100000000000000
|
||||
1110110000010000
|
||||
0000000000010001
|
||||
1110001100001000
|
||||
0000000000010001
|
||||
1111110000100000
|
||||
1110111010001000
|
||||
0000000000010001
|
||||
1111110000010000
|
||||
0000000000100000
|
||||
1110000010010000
|
||||
0000000000010001
|
||||
1110001100001000
|
||||
0000000000010000
|
||||
1111110010011000
|
||||
0000000000001010
|
||||
1110001100000001
|
||||
0000000000010111
|
||||
1110101010000111
|
||||
38
asm/asm02.py
38
asm/asm02.py
@@ -7,7 +7,7 @@
|
||||
d. HACK-Code erzeugen
|
||||
'''
|
||||
|
||||
import sys
|
||||
import sys, os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from icecream import ic
|
||||
@@ -90,26 +90,48 @@ def searchSymbols(asm):
|
||||
ist Variable @x ein int, dann ohne @ in die Symboltable übernehmen
|
||||
'''
|
||||
#ic(asm)
|
||||
i = 0
|
||||
i = 16
|
||||
for line in asm:
|
||||
if line.startswith('@'):
|
||||
ic (i, " ",line[1:])
|
||||
#ic (i, " ",line[1:])
|
||||
if line[1:].isdigit():
|
||||
ic(line[1:], " ist ein int")
|
||||
|
||||
|
||||
if line not in symboltable:
|
||||
addtoSymboltable(line, int(line[1:]))
|
||||
elif line not in symboltable:
|
||||
#ic("Symbol nicht in Table")
|
||||
addtoSymboltable(line, i)
|
||||
i = i+1
|
||||
|
||||
def ciinstruction():
|
||||
|
||||
|
||||
|
||||
def addtoSymboltable(key,value):
|
||||
ic(key, value)
|
||||
symboltable[key]=value
|
||||
|
||||
|
||||
def createAsmFile():
|
||||
datename = os.path.splitext(os.path.basename(filename))[0]+".hack"
|
||||
ic(datename)
|
||||
f = open(datename,"w")
|
||||
for line in asm:
|
||||
if line in symboltable:
|
||||
f.write('{0:016b}'.format(symboltable[line]) + "\n")
|
||||
else:
|
||||
#M=D
|
||||
f.write('1111111111111111\n')
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
#filename = sys.argv[1]
|
||||
filename = "Rect.asm"
|
||||
filename = sys.argv[1]
|
||||
#filename = "Pong.asm"
|
||||
symboltable = createSymboltable()
|
||||
asm = load_asm_file(filename)
|
||||
label_to_symboltable(asm)
|
||||
searchSymbols(asm)
|
||||
createAsmFile()
|
||||
|
||||
#print("Symtable = ",symboltable)
|
||||
|
||||
|
||||
@@ -168,8 +168,8 @@ def load_asm_file():
|
||||
|
||||
Carriage returns are removed.
|
||||
"""
|
||||
ic(Path(sys.argv[1]).expanduser().read_text().replace(
|
||||
'\r', '').split('\n'))
|
||||
#ic(Path(sys.argv[1]).expanduser().read_text().replace(
|
||||
# '\r', '').split('\n'))
|
||||
return Path(sys.argv[1]).expanduser().read_text().replace(
|
||||
'\r', '').split('\n')
|
||||
|
||||
@@ -179,18 +179,18 @@ def load_asm_file():
|
||||
Anything inside a line, after a "//" sequence is a comment.
|
||||
"""
|
||||
def filter_comment_and_blank_in_line(l):
|
||||
ic(re.sub('\s', '', l).split('//')[0])
|
||||
#ic(re.sub('\s', '', l).split('//')[0])
|
||||
return re.sub('\s', '', l).split('//')[0]
|
||||
ic([filter_comment_and_blank_in_line(l) for l in lines])
|
||||
#ic([filter_comment_and_blank_in_line(l) for l in lines])
|
||||
return [filter_comment_and_blank_in_line(l) for l in lines]
|
||||
|
||||
def remove_empty_lines(file):
|
||||
ic("remove_empty_lines ",[ l for l in file if len(l) > 0])
|
||||
#ic("remove_empty_lines ",[ l for l in file if len(l) > 0])
|
||||
return [l for l in file if len(l) > 0]
|
||||
|
||||
#ic("vor remove empty lines")
|
||||
|
||||
ic(remove_empty_lines(filter_comment_and_blank_in_lines(read_lines())))
|
||||
#ic(remove_empty_lines(filter_comment_and_blank_in_lines(read_lines())))
|
||||
|
||||
return remove_empty_lines(
|
||||
filter_comment_and_blank_in_lines(
|
||||
@@ -198,17 +198,17 @@ def load_asm_file():
|
||||
|
||||
|
||||
def is_label(line):
|
||||
ic(line)
|
||||
#ic(line)
|
||||
"""Recognise "label" declarations
|
||||
|
||||
A label is an line in the form `"(" LABEL_NAME ")"`
|
||||
"""
|
||||
ic(line.startswith('(') and line.endswith(')'))
|
||||
#ic(line.startswith('(') and line.endswith(')'))
|
||||
return line.startswith('(') and line.endswith(')')
|
||||
|
||||
|
||||
def extract_label_name(label_declaration):
|
||||
ic("extract_label_name ", label_declaration.strip('()'))
|
||||
#ic("extract_label_name ", label_declaration.strip('()'))
|
||||
"""Extract the label name from a label instruction"""
|
||||
return label_declaration.strip('()')
|
||||
|
||||
@@ -218,7 +218,7 @@ def is_a_instruction(line):
|
||||
|
||||
An A-instruction starts with "@"
|
||||
"""
|
||||
ic("is_a_instruction ",line.startswith('@'))
|
||||
#ic("is_a_instruction ",line.startswith('@'))
|
||||
return line.startswith('@')
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ def default_symbol_table():
|
||||
|
||||
|
||||
def inc_p_c(line, program_counter):
|
||||
ic("inc_p_c ", line, program_counter )
|
||||
#ic("inc_p_c ", line, program_counter )
|
||||
"""Increment `program_counter` if `line` is an instruction"""
|
||||
if is_label(line):
|
||||
return program_counter
|
||||
@@ -429,7 +429,7 @@ def get_op_code(c_instruction):
|
||||
|
||||
|
||||
def assemble_op_code_no_M(op_code):
|
||||
ic(op_code)
|
||||
#ic(op_code)
|
||||
"""Convert an assembly op code to its binary counterpart
|
||||
|
||||
Note that this method assumes that the A/M switch is made. It
|
||||
@@ -492,14 +492,14 @@ def assemble_op_code_no_M(op_code):
|
||||
|
||||
|
||||
def assemble_op_code(op_code):
|
||||
ic("assemble_op_code ", op_code)
|
||||
#ic("assemble_op_code ", op_code)
|
||||
"""Assemble the A/M switch and the op-code"""
|
||||
return ('1' if 'M' in op_code else '0') + \
|
||||
assemble_op_code_no_M(op_code.replace('M', 'A'))
|
||||
|
||||
|
||||
def assemble_c_instruction(c_instruction):
|
||||
ic("assemble_c_instruction ", c_instruction)
|
||||
#ic("assemble_c_instruction ", c_instruction)
|
||||
"""Assemble a c-instruction
|
||||
|
||||
The binary representation of a c-instruction is
|
||||
|
||||
156
asm/assembler04.py
Normal file
156
asm/assembler04.py
Normal file
@@ -0,0 +1,156 @@
|
||||
#import re
|
||||
#import sys
|
||||
import argparse
|
||||
|
||||
def convert_assembly_to_binary_file(asm_file, binary_file):
|
||||
with open(asm_file, "r") as f:
|
||||
result = translate_lines(f.readlines())
|
||||
output = "\n".join([l for l in result if l])
|
||||
with open(binary_file, "w") as f:
|
||||
f.write(output)
|
||||
|
||||
def translate_lines(lines):
|
||||
lines = strip_whitespace_and_comments(lines)
|
||||
symbol_table = build_symbol_table(lines)
|
||||
translate_instruction = build_instruction_translator(symbol_table)
|
||||
return [translate_instruction(x) for x in lines]
|
||||
|
||||
def strip_whitespace_and_comments(lines):
|
||||
instructions = []
|
||||
for line in lines:
|
||||
stripped_line = line.strip()
|
||||
if stripped_line:
|
||||
if not stripped_line.startswith("//"):
|
||||
if "//" in stripped_line:
|
||||
instructions.append(stripped_line.split("//")[0].strip())
|
||||
else:
|
||||
instructions.append(stripped_line)
|
||||
return instructions
|
||||
|
||||
def build_symbol_table(lines):
|
||||
symbols = {
|
||||
"R0": "0000000000000000",
|
||||
"R1": "0000000000000001",
|
||||
"R2": "0000000000000010",
|
||||
"R3": "0000000000000011",
|
||||
"R4": "0000000000000100",
|
||||
"R5": "0000000000000101",
|
||||
"R6": "0000000000000110",
|
||||
"R7": "0000000000000111",
|
||||
"R8": "0000000000001000",
|
||||
"R9": "0000000000001001",
|
||||
"R10": "0000000000001010",
|
||||
"R11": "0000000000001011",
|
||||
"R12": "0000000000001100",
|
||||
"R13": "0000000000001101",
|
||||
"R14": "0000000000001110",
|
||||
"R15": "0000000000001111",
|
||||
"SP": "0000000000000000",
|
||||
"ARG": "0000000000000010",
|
||||
"LCL": "0000000000000001",
|
||||
"THIS": "0000000000000011",
|
||||
"THAT": "0000000000000100",
|
||||
"KBD": "0110000000000000",
|
||||
"SCREEN": "0100000000000000"
|
||||
}
|
||||
is_address_instruction = lambda x: x.startswith("@")
|
||||
is_compute_instruction = lambda x: "=" in x or ";" in x
|
||||
label_value = lambda x: x.replace("(", "").replace(")", "").strip()
|
||||
current_line_num = 0
|
||||
for line in lines:
|
||||
if is_address_instruction(line) or is_compute_instruction(line):
|
||||
current_line_num +=1
|
||||
elif is_label(line):
|
||||
symbols[label_value(line)] = decimal_to_binary(current_line_num)
|
||||
base_address = 16
|
||||
for line in lines:
|
||||
if line.startswith("@"):
|
||||
value = line[1:]
|
||||
if value not in symbols and not value.isnumeric():
|
||||
symbols[value] = decimal_to_binary(base_address)
|
||||
base_address += 1
|
||||
return symbols
|
||||
|
||||
def build_instruction_translator(symbol_table):
|
||||
COMPUTATIONS = {
|
||||
"0": "0101010",
|
||||
"1": "0111111",
|
||||
"-1": "0111010",
|
||||
"D": "0001100",
|
||||
"A": "0110000",
|
||||
"!D": "0001101",
|
||||
"!A": "0110001",
|
||||
"-D": "0001111",
|
||||
"-A": "0110011",
|
||||
"D+1": "0011111",
|
||||
"A+1": "0110111",
|
||||
"D-1": "0001110",
|
||||
"A-1": "0110010",
|
||||
"D+A": "0000010",
|
||||
"D-A": "0010011",
|
||||
"A-D": "0000111",
|
||||
"D&A": "0000000",
|
||||
"D|A": "0010101",
|
||||
"M": "1110000",
|
||||
"!M": "1110001",
|
||||
"-M": "1110011",
|
||||
"M+1": "1110111",
|
||||
"M-1": "1110010",
|
||||
"D+M": "1000010",
|
||||
"D-M": "1010011",
|
||||
"M-D": "1000111",
|
||||
"D&M": "1000000",
|
||||
"D|M": "1010101"
|
||||
}
|
||||
DESTINATIONS = {
|
||||
"": "000",
|
||||
"M": "001",
|
||||
"D": "010",
|
||||
"MD": "011",
|
||||
"A": "100",
|
||||
"AM": "101",
|
||||
"AD": "110",
|
||||
"AMD": "111"
|
||||
}
|
||||
JUMPS = {
|
||||
"": "000",
|
||||
"JGT": "001",
|
||||
"JEQ": "010",
|
||||
"JGE": "011",
|
||||
"JLT": "100",
|
||||
"JNE": "101",
|
||||
"JLE": "110",
|
||||
"JMP": "111"
|
||||
}
|
||||
def fn(line):
|
||||
if is_label(line):
|
||||
return
|
||||
if line.startswith("@"):
|
||||
value = line[1:]
|
||||
if value in symbol_table:
|
||||
return symbol_table[value]
|
||||
return decimal_to_binary(int(value))
|
||||
dest, jump = "", ""
|
||||
comp = line.split("=").pop().split(";")[0]
|
||||
if "=" in line:
|
||||
dest = line.split("=")[0]
|
||||
if ";" in line:
|
||||
jump = line.split(";").pop()
|
||||
return f"111{COMPUTATIONS.get(comp, '0000000')}{DESTINATIONS.get(dest, '000')}{JUMPS.get(jump, '000')}"
|
||||
return fn
|
||||
|
||||
def is_label(line):
|
||||
return line.startswith("(") and line.endswith(")")
|
||||
|
||||
def decimal_to_binary(decimal_value):
|
||||
return f"{decimal_value:0>16b}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
#parser = argparse.ArgumentParser(description="Generates a hack binary file from assembly")
|
||||
#parser.add_argument("Rect.asm")
|
||||
#parser.add_argument("Rect.hack")
|
||||
#parser.add_argument("asm_file", help="name of a HACK assembly file, i.e input.asm")
|
||||
#parser.add_argument("binary_file", help="name of the HACK file, i.e output.hack")
|
||||
#args = parser.parse_args()
|
||||
#convert_assembly_to_binary_file(args.asm_file, args.binary_file)
|
||||
convert_assembly_to_binary_file('Rect.asm', 'Rect.hack')
|
||||
76
asm/assembler05.py
Normal file
76
asm/assembler05.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import re
|
||||
|
||||
acommands=[]
|
||||
asm=[]
|
||||
|
||||
dest={'':'000','M=':'001','D=':'010','MD=':'011',
|
||||
'A=':'100','AM=':'101','AD=':'110','AMD=':'111'}
|
||||
jump={'':'000',';JGT':'001',';JEQ':'010',';JGE':'011',
|
||||
';JLT':'100',';JNE':'101',';JLE':'110',';JMP':'111'}
|
||||
comp={'0':'0101010','1':'0111111','-1':'0111010','D':'0001100',
|
||||
'A':'0110000','M':'1110000','!D':'0001101','!A':'0110001',
|
||||
'!M':'1110001','-D':'0001111','-A':'0110011','-M':'1110011',
|
||||
'D+1':'0011111','A+1':'0110111','M+1':'1110111','D-1':'0001110',
|
||||
'A-1':'0110010','M-1':'1110010','D+A':'0000010','D+M':'1000010',
|
||||
'D-A':'0010011','D-M':'1010011','A-D':'0000111','M-D':'1000111',
|
||||
'D&A':'00000000','D&M':'1000000','D|A':'0010101','D|M':'1010101'}
|
||||
symbols={'SP':0,'LCL':1,'ARG':2,'THIS':3,'THAT':4,'SCREEN':16384,'KBD':24576,
|
||||
'R0':0,'R1':1,'R1':1,'R2':2,'R3':3,'R4':4,'R5':5,'R6':6,'R7':7,
|
||||
'R8':8,'R9':9,'R10':10,'R11':11,'R12':12,'R13':13,'R14':14,'R15':15}
|
||||
|
||||
f=input('File:')
|
||||
asmfile=open(f+'.asm','r')
|
||||
for line in asmfile:
|
||||
ln=re.sub(r'\/+.*\n|\n| *','',line)
|
||||
if ln!='':
|
||||
acommands.append(ln)
|
||||
asmfile.close()
|
||||
|
||||
lineno=0
|
||||
for command in acommands:
|
||||
symbol=re.findall(r'\(.+\)',command)
|
||||
if symbol!=[]:
|
||||
if symbol[0][1:-1] not in symbols:
|
||||
symbols[symbol[0][1:-1]] = lineno
|
||||
lineno-=1
|
||||
lineno+=1
|
||||
|
||||
for line in acommands:
|
||||
ln=re.sub(r'\(.+\)','',line)
|
||||
if ln!='':
|
||||
asm.append(ln)
|
||||
|
||||
variableno=16
|
||||
for command in asm:
|
||||
symbol=re.findall(r'@[a-zA-Z]+.*',command)
|
||||
if symbol!=[]:
|
||||
if symbol[0][1:] not in symbols:
|
||||
symbols[symbol[0][1:]] = variableno
|
||||
variableno+=1
|
||||
|
||||
hackfile=open(f+'1.hack','w')
|
||||
for command in asm:
|
||||
if command[0]=='@':
|
||||
address=0
|
||||
if command[1:] in symbols:
|
||||
address=symbols[command[1:]]+32768
|
||||
else:
|
||||
address=int(command[1:])+32768
|
||||
hackfile.write('0'+bin(address)[3:]+'\n')
|
||||
else:
|
||||
de=re.findall(r'.+=',command)
|
||||
if de!=[]:
|
||||
d=dest[str(de[0])]
|
||||
else:
|
||||
d=dest['']
|
||||
|
||||
je=re.findall(r';.+',command)
|
||||
if je!=[]:
|
||||
j=jump[str(je[0])]
|
||||
else:
|
||||
j=jump['']
|
||||
|
||||
c=comp[re.sub(r'.+=|;.+','',command)]
|
||||
hackfile.write('111'+c+d+j+'\n')
|
||||
|
||||
hackfile.close()
|
||||
Reference in New Issue
Block a user