public static void ResolveIncludes(AsmSource asmSource) { string[] lines = asmSource.Text.Split( new[] { Environment.NewLine }, StringSplitOptions.None ); string newText = ""; foreach (var line in lines) { if (line.Trim().ToLower().StartsWith("#include")) { var fileName = line.Trim().Substring(8).Trim(); var linesIncludeFile = File.ReadAllLines(fileName); foreach (var lineInclude in linesIncludeFile) { newText += lineInclude + Environment.NewLine; } } else { newText += line + Environment.NewLine; } } asmSource.Text = newText; }
public static void ConvertTokensToMachineCode(AsmSource asmSource) { var nextProgramAddress = 0; foreach (var line in asmSource.Lines) { if (line.Address >= nextProgramAddress) { // Fill bytes with zeroes when there is a gap between // instructions (caused by an #org directive) var start = nextProgramAddress; for (var i = start; i < line.Address; i++) { asmSource.Bytes.Add(0); nextProgramAddress++; } asmSource.Bytes.AddRange(ConvertLineTokensToMachineCode(line)); nextProgramAddress += 3; } else { var bytes = ConvertLineTokensToMachineCode(line); asmSource.Bytes[line.Address] = bytes[0]; asmSource.Bytes[line.Address + 1] = bytes[1]; asmSource.Bytes[line.Address + 2] = bytes[2]; } } var lastAddr = nextProgramAddress; foreach (var defMem in asmSource.DefMems) { var address = defMem.Key; var value = Convert.ToByte(defMem.Value); if (address >= lastAddr) { // Fill space between end of program (or last defmem addr) // and defmem addr for (int i = lastAddr; i < address; i++) { asmSource.Bytes.Add(0); lastAddr++; } asmSource.Bytes.Add(value); lastAddr++; } else { asmSource.Bytes[address] = value; } } }
public static AsmSource SourceToMachineCode(string source) { var asmSource = new AsmSource(source); AssemblerClass.ResolveIncludes(asmSource); AssemblerClass.ConvertToTokens(asmSource); AssemblerClass.ResolveLabelsAndDirectives(asmSource); AssemblerClass.ConvertTokensToMachineCode(asmSource); return(asmSource); }
public static void ConvertToTokens(AsmSource asmSource) { var lines = asmSource.Text.Split( new[] { Environment.NewLine }, StringSplitOptions.None ); foreach (var line in lines) { Line newLine = ConvertLineToTokens(line); if (newLine.Tokens.Count > 0) { asmSource.Lines.Add(newLine); } } }
/// <summary> /// Identifies and resolves Labels and Variables /// </summary> /// <param name="asmSource"></param> public static void ResolveLabelsAndDirectives(AsmSource asmSource) { var programAddress = 0; var varAddress = 0xc00; var defMemLastAddress = 0; foreach (var line in asmSource.Lines) { if (line.IsLabelDefinition()) { asmSource.Labels.Add(new KeyValuePair <string, int>( line.Tokens[0].Text, programAddress)); } else if (line.IsVariableDefinition()) { asmSource.Variables.Add(new KeyValuePair <string, int>( line.Tokens[1].Text, varAddress)); varAddress++; } else if (line.IsOrgDirective()) { programAddress = ((LiteralToken)line.Tokens[1]).NumericValue; } else if (line.IsDefMemDirective()) { var address = 0; var value = 0; if (line.Tokens.Count == 3) { address = ((LiteralToken)line.Tokens[1]).NumericValue; defMemLastAddress = address; value = ((LiteralToken)line.Tokens[2]).NumericValue; } else if (line.Tokens.Count == 2) { defMemLastAddress++; address = defMemLastAddress; value = ((LiteralToken)line.Tokens[1]).NumericValue; } asmSource.DefMems.Add(new KeyValuePair <int, int>( address, value)); } else { line.Address = programAddress; programAddress += 3; } } IList <Line> newLines = new List <Line>(); foreach (var line in asmSource.Lines) { try { // if is label definition or defbyte, drop line if (line.IsLabelDefinition() || line.IsVariableDefinition() || line.IsOrgDirective() || line.IsDefMemDirective()) { continue; } // if has label or variable in line, resolve it // (convert to corresponding memory address) IList <Token> newTokens = new List <Token>(); foreach (var token in line.Tokens) { if (token is LabelToken) { var literal = asmSource.Labels[token.Text].ToString(); var literalToken = new LiteralToken(literal); newTokens.Add(literalToken); } else if (token is DirectiveToken) { var address = asmSource.Variables[token.Text].ToString(); var addressToken = new AddressToken(address); newTokens.Add(addressToken); } else { newTokens.Add(token); } } line.Tokens.Clear(); line.Tokens = newTokens; newLines.Add(line); } catch (Exception ex) { throw new Exception("Error in line: " + line.Text, ex); } } asmSource.Lines.Clear(); asmSource.Lines = newLines; }