-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAssembler.cs
More file actions
103 lines (92 loc) · 3.6 KB
/
Assembler.cs
File metadata and controls
103 lines (92 loc) · 3.6 KB
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
using System;
using System.IO;
using System.Collections.Generic;
///<summary>
///A basic Assembler program for the Hack computer that translates the Hack symbolic language
///into binary code that can execute on the Hack hardware platform. Built as part of the nand2tetris
///course by Shimon Schocken and Noam Nisan, further information at www.nand2tetris.org.
///</summary>
namespace Assembler
{
class Program
{
const string HackFileExtension = ".hack";
static void Main(string[] args)
{
if(args.Length == 0)
{
Console.WriteLine("No argument given. Path for input file must be specified.");
return;
}
//read file
Parser parser = new Parser(args[0]);
//First pass: set memory locations for labels (LABEL)
int currentAddress = 0;
while(parser.HasMoreCommands())
{
Parser.CommandType commandType = parser.GetCommandType();
if(commandType == Parser.CommandType.L_COMMAND)
SymbolTable.AddSymbol(parser.Symbol(), (short)currentAddress);
else
currentAddress++;
parser.Advance();
}
parser.Reset();
//Second pass: generate machine code
List<string> hackCode = new List<string>();
while(parser.HasMoreCommands())
{
string newLine = string.Empty;
Parser.CommandType commandType = parser.GetCommandType();
if(commandType == Parser.CommandType.A_COMMAND)
{
short address = SymbolTable.GetAddress(parser.Symbol());
newLine = Convert.ToString(address, 2).PadLeft(16, '0');
if(string.IsNullOrWhiteSpace(newLine))
{
newLine = UnknownCommand();
}
}
else if(commandType == Parser.CommandType.C_COMMAND)
{
string comp = Code.Comp(parser.Comp());
string dest = Code.Dest(parser.Dest());
string jump = Code.Jump(parser.Jump());
newLine = comp + dest + jump;
if(string.IsNullOrWhiteSpace(comp) || string.IsNullOrWhiteSpace(dest)
|| string.IsNullOrWhiteSpace(jump))
{
newLine = UnknownCommand();
}
else
newLine = newLine.PadLeft(16, '1');
}
if(!string.IsNullOrWhiteSpace(newLine))
hackCode.Add(newLine);
parser.Advance();
}
if(hackCode.Count > 0)
SaveHackCodeFile(hackCode, args[0]);
else
Console.WriteLine("Nothing to write.");
}
private static string UnknownCommand()
{
Console.WriteLine("Unknown command found.");
return "##UNKNOWN-CMD###";
}
private static void SaveHackCodeFile(List<string> hackCode, string filePath)
{
try
{
string directoryPath = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileNameWithoutExtension(filePath);
File.WriteAllLines(directoryPath + @"\" + fileName + HackFileExtension, hackCode);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}