예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }