Esempio n. 1
0
        public void ReadHexFile(string sourceFile)
        {
            using (var reader = new StreamReader(sourceFile))
            {
                HexResult = reader.ReadToEnd();

                // remove the colon and next 4 bytes (8 chars) - ":1D000000"
                bool found = true;
                while (found)
                {
                    var pos = HexResult.IndexOf(":", StringComparison.Ordinal);

                    if (pos > -1)
                    {
                        HexResult = HexResult.Remove(pos, 9);
                    }
                    else
                    {
                        found = false;
                    }
                }
            }
        }
Esempio n. 2
0
        public void AssembleCode()
        {
            string[] regPair;
            string   tempData;

            CurrentAddress = 0;
            HexResult      = "";
            HexTestResult  = "";


            using (var reader = new StringReader(AssemblyCode))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    var sourceLine = new SourceLine(line);

                    if (sourceLine.Label != "" && sourceLine.OpCode != OpcodeEnum.EQU)
                    {
                        if (!_labels.ContainsKey(sourceLine.Label))
                        {
                            _labels.Add(sourceLine.Label, new LabelRecord
                            {
                                name = CurrentAddress.ToHex().PadLeft(4, '0').SwapHex(),
                                size = 2
                            }
                                        );
                        }
                        else
                        {
                            if (_labels[sourceLine.Label].name == "")
                            {
                                _labels[sourceLine.Label].name = CurrentAddress.ToHex().PadLeft(4, '0').SwapHex();
                                _labels[sourceLine.Label].size = 2;
                            }
                            else
                            {
                                throw new Exception("Labels can only be defined once!");
                            }
                        }
                    }

                    if (sourceLine.OpCode == OpcodeEnum.NONE && sourceLine.Operand == "")
                    {
                        // must be a comment line
                        continue;
                    }

                    HexTestResult += CurrentAddress.ToHex().PadLeft(4, '0') + "  ";

                    switch (sourceLine.OpCode)
                    {
                    case OpcodeEnum.DB:
                        tempData = ReadByteData(sourceLine.Operand);

                        CurrentAddress += tempData.Length / 2;
                        AppendHexResult(tempData);
                        break;

                    case OpcodeEnum.DW:
                        tempData = ReadWordData(sourceLine.Operand);

                        CurrentAddress += tempData.Length / 2;
                        AppendHexResult(tempData);
                        break;

                    case OpcodeEnum.DS:                         // reserve memory space
                    case OpcodeEnum.ORG:                        // origin

                        int total = 0;
                        if (sourceLine.Operand.IsHex())
                        {
                            total = sourceLine.Operand.HexToInt();
                        }
                        else
                        {
                            total = sourceLine.Operand.ToInt();
                        }

                        CurrentAddress += total;

                        for (int i = 0; i < total; i++)
                        {
                            HexResult += "00";
                        }
                        break;

                    case OpcodeEnum.END:
                        break;

                    case OpcodeEnum.EQU:
                        if (!_labels.ContainsKey(sourceLine.Label))
                        {
                            _labels.Add(sourceLine.Label, new LabelRecord {
                                name = ParseFormula(sourceLine.Operand, 1), size = 2
                            });
                        }
                        else
                        {
                            _labels[sourceLine.Label].name = ParseFormula(sourceLine.Operand, 1);
                            _labels[sourceLine.Label].size = 2;
                        }
                        break;

                    case OpcodeEnum.ACI:
                        AppendHexResult("CE ");
                        AppendHexResult(sourceLine.Operand.ToHex());
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ADC:
                        AppendHexResult((0x88 + SourceRegisterNumber(sourceLine.Operand)).ToHex());
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ADD:
                        AppendHexResult((0x80 + SourceRegisterNumber(sourceLine.Operand)).ToHex());
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ADI:
                        AppendHexResult("C6 " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ANA:
                        AppendHexResult((0xa0 + SourceRegisterNumber(sourceLine.Operand)).ToHex());
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ANI:
                        AppendHexResult("E6 " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CALL:
                        AppendHexResult("CD " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CC:
                        AppendHexResult("DC " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CM:
                        AppendHexResult("FC " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CMA:
                        AppendHexResult("2F ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CMC:
                        AppendHexResult("3F ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CMP:
                        AppendHexResult((0xb8 + SourceRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CNC:
                        AppendHexResult("D4 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CNZ:
                        AppendHexResult("C4 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CP:
                        AppendHexResult("F4 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CPE:
                        AppendHexResult("EC " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CPI:
                        AppendHexResult("FE " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CPO:
                        AppendHexResult("E4 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.CZ:
                        AppendHexResult("CC " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.DAA:
                        AppendHexResult("27 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.DAD:
                        AppendHexResult((0x09 + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.DCR:
                        AppendHexResult((0x05 + DestinationRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.DCX:
                        AppendHexResult((0x0b + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.DI:
                        AppendHexResult("F3 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.EI:
                        AppendHexResult("FB ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.HLT:
                        AppendHexResult("76 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.IN:
                        AppendHexResult("DB " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.INR:
                        AppendHexResult((0x04 + DestinationRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.INX:
                        AppendHexResult((0x03 + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JC:
                        AppendHexResult("DA " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JM:
                        AppendHexResult("FA " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JMP:
                        AppendHexResult("C3 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JNC:
                        AppendHexResult("E2 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JNZ:
                        AppendHexResult("C2 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JP:
                        AppendHexResult("F2 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JPE:
                        AppendHexResult("EA " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JPO:
                        AppendHexResult("E2 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.JZ:
                        AppendHexResult("CA " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.LDA:
                        AppendHexResult("3A " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.LDAX:
                        AppendHexResult((0x0a + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.LHLD:
                        AppendHexResult("2A " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.LXI:
                        regPair = sourceLine.Operand.Split(',');
                        AppendHexResult((0x01 + DoubleRegisterNumber(regPair[0])).ToHex() + " " + GetOperand(regPair[1], 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.MOV:
                        regPair = sourceLine.Operand.Split(',');
                        AppendHexResult((0x40 + DestinationRegisterNumber(regPair[0]) + SourceRegisterNumber(regPair[1])).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.MVI:
                        regPair = sourceLine.Operand.Split(',');
                        AppendHexResult((0x06 + DestinationRegisterNumber(regPair[0])).ToHex() + " " + GetOperand(regPair[1], 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.NOP:
                        AppendHexResult("00 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ORA:
                        AppendHexResult((0xb0 + SourceRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.ORI:
                        AppendHexResult("F6 " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.OUT:
                        AppendHexResult("D3 " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.PCHL:
                        AppendHexResult("E9 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.POP:
                        AppendHexResult((0xc1 + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.PUSH:
                        AppendHexResult((0xc5 + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RAL:
                        AppendHexResult("17 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RAR:
                        AppendHexResult("1F ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RC:
                        AppendHexResult("D8 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RET:
                        AppendHexResult("C9 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RLC:
                        AppendHexResult("03 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RM:
                        AppendHexResult("F8 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RNC:
                        AppendHexResult("D0 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RNZ:
                        AppendHexResult("C0 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RP:
                        AppendHexResult("F0 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RPE:
                        AppendHexResult("E8 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RPO:
                        AppendHexResult("E0 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RRC:
                        AppendHexResult("0F ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.RZ:
                        AppendHexResult("C8 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SBB:
                        AppendHexResult((0x98 + SourceRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SBI:
                        AppendHexResult("DE " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SHLD:
                        AppendHexResult("22 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SIM:
                        AppendHexResult("30 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SPHL:
                        AppendHexResult("F9 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.STA:
                        AppendHexResult("32 " + GetOperand(sourceLine.Operand, 2));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.STAX:
                        AppendHexResult((0x02 + DoubleRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.STC:
                        AppendHexResult("37 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SUB:
                        AppendHexResult((0x90 + SourceRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.SUI:
                        AppendHexResult("D6 " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.XCHG:
                        AppendHexResult("EB ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.XRA:
                        AppendHexResult((0xa8 + SourceRegisterNumber(sourceLine.Operand)).ToHex() + " ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.XRI:
                        AppendHexResult("EE " + GetOperand(sourceLine.Operand, 1));
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    case OpcodeEnum.XTHL:
                        AppendHexResult("E3 ");
                        CurrentAddress += sourceLine.InstructionSize;
                        break;

                    default:

                        break;
                    }

                    /*
                     * if (currentAddress != HexResult.Replace("\n", "").Length / 2)
                     * {
                     *      throw new Exception("address incorrect");
                     * }
                     *
                     */
                    HexTestResult += "\n";
                }
            }

            foreach (var item in _labels)
            {
                // verify all labels have addresses
                if (item.Value.name == "")
                {
                    // this label could be a formula.
                    var result = ParseFormula(item.Key, 2);

                    if (result.Contains("|"))
                    {
                        throw new Exception($"missing label {item.Key}");
                    }
                    else
                    {
                        HexResult     = HexResult.Replace("|" + item.Key + "|", result.PadRight(item.Value.size * 2, '0'));
                        HexTestResult = HexTestResult.Replace("|" + item.Key + "|", result.PadRight(item.Value.size * 2, '0').SpaceByBytes());
                    }
                }
                else
                {
                    // replace label names in hexdata with addresses
                    HexResult     = HexResult.Replace("|" + item.Key + "|", item.Value.name.PadRight(item.Value.size * 2, '0'));
                    HexTestResult = HexTestResult.Replace("|" + item.Key + "|", item.Value.name.PadRight(item.Value.size * 2, '0').SpaceByBytes());
                }
            }

            HexResult = HexResult.Replace(" ", "");

            if (HexResult.Contains("|"))
            {
                throw new Exception("Label replace failure");
            }
        }