Skip to content

Commit

Permalink
Hack assembler complete. Done hardware course
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennis-Johnson committed Oct 22, 2021
1 parent 6f09335 commit 10fae89
Show file tree
Hide file tree
Showing 10 changed files with 27,580 additions and 28 deletions.
20 changes: 14 additions & 6 deletions projects/06/Instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ def getBinaryTranslation(self) -> str:
# Compute Instruction
class CInstruction:
def __init__(self, line) -> None:
destSplit = line.split("=")
self.dest = destSplit[0].strip() if len(destSplit) > 1 else "null"

jumpSplit = destSplit[1].split(";")
self.jump = jumpSplit[1].strip() if len(jumpSplit) > 1 else "null"
self.comp = jumpSplit[0]
# Only comp and jump field, no dest field.
if line.find('=') == -1:
self.dest = "null"
jumpSplit = line.split(';')
self.comp = jumpSplit[0].strip()
self.jump = jumpSplit[1].strip()

# Only comp and dest field, no jump field.
else:
self.jump = "null"
destSplit = line.split('=')
self.dest = destSplit[0].strip()
self.comp = destSplit[1].strip()


def __str__(self) -> str:
return "[C]: Dest (" + self.dest + "), Comp (" + self.comp +"), Jump (" + self.jump + ")"
Expand Down
Empty file removed projects/06/Max.hack
Empty file.
32 changes: 25 additions & 7 deletions projects/06/Parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,35 @@ def __init__(self, filePath) -> None:
self.currentLineNumber = 0

self.symbolTable = SymbolTable()
# First pass to add labels to symbol table.

# First pass to add just labels to symbol table.
self.addLabels()


def hasMoreCommands(self) -> bool:
return self.currentLineNumber < len(self.inputLines)

def getNextCommand(self) -> Union[AInstruction, CInstruction]:
# Skip over lines with only whitespace or comments.
# Skip over lines with only whitespace, comments, or labels.
while self.__getStrippedLine(self.currentLineNumber) == '':
self.currentLineNumber += 1
line = self.inputLines[self.currentLineNumber]

cmd = AInstruction(line) if line[0] == '@' else CInstruction(line)
if line.startswith('@'):
if line[1:].isnumeric():
cmd = AInstruction(line)

# Otherwise, it's a symbol
else:
symbolName = line[1:]
if not self.symbolTable.contains(symbolName):
self.symbolTable.addVariable(symbolName)

cmd = AInstruction("@" + str(self.symbolTable.getAddress(symbolName)))
else:
cmd = CInstruction(line)

self.currentLineNumber += 1

return cmd

# Strips a line of comments and whitespace and returns it.
Expand All @@ -40,7 +53,14 @@ def __getStrippedLine(self, lineNumber:int) -> str:

# Returns -1 if no comments are found.
commentStartIndex = self.inputLines[lineNumber].find("//")
return self.inputLines[lineNumber] if commentStartIndex == -1 else self.inputLines[lineNumber][:commentStartIndex]
if not commentStartIndex == -1:
self.inputLines[lineNumber] = self.inputLines[lineNumber][:commentStartIndex].strip()

# Clears line if it's a label
if self.inputLines[lineNumber].startswith('(') and self.inputLines[lineNumber].endswith(')'):
self.inputLines[lineNumber] = ""

return self.inputLines[lineNumber]

# First pass where all labels and their addresses are identified. No translation yet.
def addLabels(self) -> None:
Expand All @@ -63,5 +83,3 @@ def addLabels(self) -> None:
# Increment counter when you find an A or C instruction.
else:
lineNumber += 1

print(self.symbolTable.symbols)
26 changes: 15 additions & 11 deletions projects/06/SymbolTable.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
Defines a class to handle symbols encountered during the Hack assembly translation.
'''

from typing import List


class SymbolTable:
def __init__(self) -> None:
# Add some predefined symbols to the symbol table.
Expand All @@ -26,23 +23,30 @@ def __init__(self) -> None:
"R7": 7,
"R8": 8,
"R9": 9,
"R10": 11,
"R11": 12,
"R12": 13,
"R13": 14,
"R14": 15,
"R15": 16,
"R10": 10,
"R11": 11,
"R12": 12,
"R13": 13,
"R14": 14,
"R15": 15,
"SCREEN": 16384,
"KBD": 24576
}

# The next RAM address to which a symbol can be assigned
self.nextAvailableAddress = 17
self.nextAvailableAddress = 16

# Adds a (symbol, address) pair to the symbol table.
# Adds a (symbol, address) pair to the symbol table. Used for labels.
def addSymbol(self, symbol:str, address: int) -> None:
assert self.nextAvailableAddress < 16384, "Symbol Table is full"
self.symbols[symbol] = address

# Adds a (symbol, address) pair to the symbol table. Used for variables.
def addVariable(self, symbol:str) -> None:
assert self.nextAvailableAddress < 16384, "Symbol Table is full"
self.symbols[symbol] = self.nextAvailableAddress
self.nextAvailableAddress += 1

def contains(self, symbol:str) -> bool:
return True if symbol in self.symbols else False

Expand Down
4 changes: 1 addition & 3 deletions projects/06/assembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ def assembler(filePath):
parser = Parser(filePath)
translatedLines = []

'''
while parser.hasMoreCommands():
cmd = parser.getNextCommand()
print(cmd.__str__() + " --> " + cmd.getBinaryTranslation())
translatedLines.append(cmd.getBinaryTranslation())
'''

# Write lines to the .hack file"
# Write translated lines to the .hack file"
with open(fileName + ".hack", "w") as binFile:
for line in translatedLines:
print(line, file = binFile)
Expand Down
File renamed without changes.
16 changes: 16 additions & 0 deletions projects/06/generated/Max.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
0000000000000000
1111110000010000
0000000000000001
1111010011010000
0000000000001010
1110001100000001
0000000000000001
1111110000010000
0000000000001100
1110101010000111
0000000000000000
1111110000010000
0000000000000010
1110001100001000
0000000000001110
1110101010000111
Loading

0 comments on commit 10fae89

Please sign in to comment.