private OperandMatch MatchOperand(string value) { value = value.Trim(); OperandMatch match = new OperandMatch(); match.Original = value; if (m_registerTable.ContainsKey(value)) { match.IsRegister = true; match.Register = m_registerTable[value]; } else { match.IsRegister = false; match.Literal = value; } return(match); }
public void Assemble(string codeFile) { string[] lines = File.ReadAllLines(codeFile); for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); FileEntry entry = new FileEntry(line, codeFile, i + 1, m_currentAddress); string[] parts; if (String.IsNullOrWhiteSpace(line) || line[0] == ';') { // Save raw line for listing. m_entries.Add(entry); continue; } // Trim off comments for proper processing. line = line.Split(';')[0].Trim(); if (line[0] == '#') // Line is a directive. { entry.CodeType = CodeType.Directive; parts = line.Split(new[] { ' ', '\t' }, 3, StringSplitOptions.RemoveEmptyEntries); if (parts[0] == "#equ") { m_variableTableFirstPass[parts[1]] = parts[2]; } else if (parts[0] == "#at") { m_currentAddress = parts[1][0] == 'h' ? UInt32.Parse(parts[1].Substring(1), NumberStyles.HexNumber) : UInt32.Parse(parts[1]); entry.Address = m_currentAddress; } } else if (line[0] == ':') // Line is label. { entry.CodeType = CodeType.Label; parts = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); m_lableTable[parts[0].Substring(1)] = m_currentAddress; } else { OpCodeMatch match = MatchOpCode(line); if (match == null) { entry.ErrorCode = ErrorCode.InvalidOpcode; m_errorEntries.Add(entry); continue; } entry.OpCode = match; entry.Output = match.OpCode.Value; entry.CodeType = CodeType.Instruction; var opA = MatchOperand(match.OperandA); OperandMatch opB = null; if (!String.IsNullOrWhiteSpace(match.OperandB)) { opB = MatchOperand(match.OperandB); } entry.OperandA = opA; entry.OperandB = opB; if (OperandErrorCheck(entry)) { entry.ErrorCode = ErrorCode.InvalidOperands; m_errorEntries.Add(entry); continue; } if ((match.OpCode.Value == 0x8800 || match.OpCode.Value == 0xB000 || match.OpCode.Value == 0x5000 || match.OpCode.Value == 0x5800) && opA.Register == opB.Register) { entry.WarningCode = WarningCode.RedundantStatement; m_warningEntries.Add(entry); } m_currentAddress++; if (opA?.IsRegister != true) // First 7 instructions are the jump instructions. { m_currentAddress++; } if (opB != null && opB.IsRegister != true && match.OpCode.Value != 0x9000) // SETI instruction doesn't need second word. { m_currentAddress++; } } m_entries.Add(entry); } }