/// <summary> /// Обрабатывает команду. В случае, если команда некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, содержащая команду процессора.</param> /// <param name="env">Текущее окружение компилятора, в которое записывается команда.</param> public void HandleCommand(string line, CompilerEnvironment env) { string command; string[] args; line = line.Trim(); int firstSpaceIndex = line.IndexOf(" "); if (firstSpaceIndex == -1) { command = line; args = new string[0]; } else { command = line.Substring(0, firstSpaceIndex); args = line.Substring(firstSpaceIndex + 1).Split(',').Select(x => x.Trim()).ToArray(); } command = command.ToLower(); if (!_commandProcessors.ContainsKey(command)) { throw new CompilationErrorExcepton("Неверная команда", env.GetCurrentLine()); } _commandProcessors[command](args, env); }
/// <summary> /// Функция, начинающая обработку кода и содержащая базовую логику прохождения по нему и вызова обработчиков. /// </summary> private void StartCompile(object sender, DoWorkEventArgs e) { List <string> lines = PrepareCode(_code); var env = new CompilerEnvironment(); for (short i = 0; i < lines.Count; i++) { if (lines[i].Length == 0) { env.IncrementLine(); continue; } if (lines[i][0] == '/') { HandleDirective(lines[i], env); env.IncrementLine(); continue; } string line = HandleLabelAndReturnLine(lines[i], env); bool isSuccess = TryToGetVariable(line, env); if (!isSuccess) { HandleCommand(line, env); } env.IncrementLine(); } var commandWithoutLabel = env.FirstCommandWithoutLabel(); if (commandWithoutLabel.HasValue) { throw new CompilationErrorExcepton($"Метка {commandWithoutLabel.Value.Value} не определена", commandWithoutLabel.Value.Key); } e.Result = env; }
/// <summary> /// Пытается достать из строки объявление переменной. /// Если в строке нет слова eql, то возвращает false, /// Если есть и строка имеет формат *идетификатор* eql *адрес*, то пытается сохранить адрес за идентификатором /// Если есть, но строка не подходит по формату, выбрасывает исключение <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода для обработки.</param> /// <param name="env">Окружение компилятора.</param> /// <returns>True, если в строке присутствовала переменная, false, если нет.</returns> public bool TryToGetVariable(string line, CompilerEnvironment env) { if (!line.Contains(" eql ")) { return(false); } var args = line.Split(' ').Select(x => x.ToLower().Trim()).ToArray(); if (args.Length != 3 || !args[1].Equals("eql", StringComparison.OrdinalIgnoreCase)) { throw new CompilationErrorExcepton("Объявление переменной должно соответствовать формату *имя переменной* eql *адрес*.", env.GetCurrentLine()); } bool isIdentifierCorrect = CompilerSupport.CheckIdentifierName(args[0]); if (!isIdentifierCorrect) { throw new CompilationErrorExcepton("Имя переменной должно содержать только латиские буквы, цифры знаки тире и подчеркивания и начинаться с буквы.", env.GetCurrentLine()); } int address = CompilerSupport.ConvertToInt(args[2]); if (address > 255) { throw new CompilationErrorExcepton("Адрес не может превышать 255", env.GetCurrentLine()); } if (env.IsIdentifierExist(args[0])) { throw new CompilationErrorExcepton($"Идентификатор с именем {args[0]} уже существует.", env.GetCurrentLine()); } env.AddVariable(args[0], address); return(true); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { int register = CompilerSupport.ConvertToInt(args[0]); if (register < 0 || register > 127) { throw new CompilationErrorExcepton("Номер регистра должен быть числом от 0 до 127", env.GetCurrentLine()); } int bit = CompilerSupport.ConvertToInt(args[1]); if (bit < 0 || bit > 7) { throw new CompilationErrorExcepton("Номер бита должен быть числом от 0 до 7", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [7] = true, [5] = true } }; CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, register, 7); CompilerSupport.FillBitArray(null, dataResponse.highBitArray, bit, 3); return(dataResponse); }
private static void POP(string[] args, CompilerEnvironment env) { if (args.Length != 1) { throw new CompilationErrorExcepton("Оператор POP должен принимать 1 аргумент.", env.GetCurrentLine()); } var r = CompilerSupport.ConvertToRegister(args[0]); if (!r.HasValue) { throw new CompilationErrorExcepton("Аргументом должен быть регистр.", env.GetCurrentLine()); } var registr = r.Value; if (!registr.IsDirect) { throw new CompilationErrorExcepton("Адресация регистра должна быть прямой.", env.GetCurrentLine()); } var highBitArray = new BitArray(8) { [6] = true, [4] = true, [3] = true, [2] = true, [0] = true }; var lowBitArray = new BitArray(8); CompilerSupport.FillBitArray(null, lowBitArray, registr.Number, 4); env.SetByte(lowBitArray); env.SetByte(highBitArray); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [5] = true, [6] = true } }; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; return(dataResponse); } int address = CompilerSupport.ConvertVariableToAddress(args[0], env); if (address == -1) { throw new CompilationErrorExcepton($"Переменной с именем {args[0]} не существует.", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, Constants.ShortAddressBitsCount); return(dataResponse); }
/// <summary> /// Приводит переданную строку к полному, 10-битовому адресу. /// Если введен слишком большой адрес или строка не является меткой, /// будет сгенерированно исключение <see cref="CompilerEnvironment"/>. /// </summary> /// <param name="label">Строка-метка или адрес в памяти.</param> /// <param name="env">Текущее окружение компилятора.</param> /// <returns>Адресс, на который ссылается метка или который был записан как число, или -1, если использована несуществующая метка.</returns> public static int ConvertLabelToFarAddress(string label, CompilerEnvironment env) { try { if (label[0] >= '0' && label[0] <= '9') { int address = ConvertToInt(label); if (address > MaxFarAddress) { throw new OverflowException(); } return(address); } else { int address = env.GetLabelAddress(label); return(address); } } catch (OverflowException) { throw new CompilationErrorExcepton($"Адрес не должен превышать {MaxFarAddress}", env.GetCurrentLine()); } catch (FormatException) { throw new CompilationErrorExcepton("Некорректный адрес метки", env.GetCurrentLine()); } catch (Exception e) { throw new CompilationErrorExcepton("Непредвиденная ошибка при обработке метки", env.GetCurrentLine(), e); } }
private static void NOT(string[] args, CompilerEnvironment env) { var dataResponse = GetBitArrays(args, "NOT", env); env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static DataResponse GetBitArrays(string[] args, CompilerEnvironment env) { var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) { [7] = true } }; int address = CompilerSupport.ConvertVariableToAddress(args[0], env); if (address == -1) { throw new CompilationErrorExcepton($"Переменной с именем {args[0]} не существует.", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, Constants.ShortAddressBitsCount); int bit = CompilerSupport.ConvertToInt(args[1]); if (bit >= 1 << 3 || bit < 0) { throw new CompilationErrorExcepton("Номер бита не должен превышать 7", env.GetCurrentLine()); } CompilerSupport.FillBitArray(null, dataResponse.highBitArray, bit, 3); return(dataResponse); }
private static void CMP(string[] args, CompilerEnvironment env) { var dataResponse = GetBitArrays(args, "CMP", env); dataResponse.highBitArray[3] = true; env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static void CB(string[] args, CompilerEnvironment env) { Validate(args, "CB", env.GetCurrentLine()); var dataResponse = GetBitArrays(args, env); env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static void RET(string[] args, CompilerEnvironment env) { ValidateNoAddressCommand(args, "RET", env.GetCurrentLine()); var array = new ExtendedBitArray() { [1] = true }; env.SetByte(array); env.SetByte(new ExtendedBitArray()); }
private static void EI(string[] args, CompilerEnvironment env) { ValidateNoAddressCommand(args, "EI", env.GetCurrentLine()); var array = new BitArray(8) { [2] = true }; env.SetByte(array); env.SetByte(new BitArray(8)); }
private static void XOR(string[] args, CompilerEnvironment env) { var dataResponse = GetBitArrays(args, "XOR", env); dataResponse.highBitArray[0] = true; dataResponse.highBitArray[1] = true; dataResponse.highBitArray[2] = true; env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static void SBISC(string[] args, CompilerEnvironment env) { Validate(args, "SBISC", env.GetCurrentLine()); var dataResponse = GetBitArrays(args, env); dataResponse.highBitArray[3] = true; dataResponse.highBitArray[4] = true; env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static void CALL(string[] args, CompilerEnvironment env) { Validate(args, "CALL", env.GetCurrentLine()); var highBitArray = new BitArray(8); var lowBitArray = new BitArray(8); highBitArray[3] = true; highBitArray[6] = true; FillAddressAndSetCommand(highBitArray, lowBitArray, args[0], env); }
private static void JNZ(string[] args, CompilerEnvironment env) { Validate(args, "JNZ", env.GetCurrentLine()); var lowBitArray = new BitArray(8); var highBitArray = new BitArray(8) { [5] = true }; FillAddressAndSetCommand(highBitArray, lowBitArray, args[0], env); }
private static void JC(string[] args, CompilerEnvironment env) { Validate(args, "JC", env.GetCurrentLine()); var lowBitArray = new ExtendedBitArray(); var highBitArray = new ExtendedBitArray() { [2] = true, [4] = true, [5] = true }; FillAddressAndSetCommand(highBitArray, lowBitArray, args[0], env); }
private static void DJRNZ(string[] args, CompilerEnvironment env) { if (args.Length != 2) { throw new CompilationErrorExcepton("Оператор DJRNZ должен принимать ровно 2 аргумента.", env.GetCurrentLine()); } var R = CompilerSupport.ConvertToRegister(args[0]); if (!R.HasValue) { throw new CompilationErrorExcepton("Первым аргументом должен быть регистр.", env.GetCurrentLine()); } var register = R.Value; if (!register.IsDirect) { throw new CompilationErrorExcepton("В этой команде нельзя использовать косвенную адерсацию.", env.GetCurrentLine()); } if (register.Number > 3) { throw new CompilationErrorExcepton("В этой команде можно использовать только первые 4 регистра.", env.GetCurrentLine()); } string L = args[1]; int address = CompilerSupport.ConvertLabelToFarAddress(L, env); var lowBitArray = new BitArray(8); var highBitArray = new BitArray(8) { [2] = (register.Number & 1) != 0, [3] = (register.Number & 2) != 0, [4] = true }; if (address == -1) { var memoryForLabel = new CompilerEnvironment.MemoryForLabel { HighBitArray = highBitArray, LowBitArray = lowBitArray, Address = env.CurrentAddress }; env.SetCommandWithoutLabel(memoryForLabel, L); return; } CompilerSupport.FillBitArray(highBitArray, lowBitArray, address, Constants.FarAddressBitsCount); env.SetByte(lowBitArray); env.SetByte(highBitArray); }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line[1] == 'n' || line[1] == 'N') { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /n должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if (line[1] == 'D' || line[1] == 'd') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }
/// <summary> /// Проверяет, присутствует ли в строке метка, и если она есть, добавляет метку в окружение и удаляет ее из строки. /// Если имя метки некорректно или занято, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, которая проверяется на наличие метки.</param> /// <param name="env">Текущее окружение компилятора, в которое добавляется метка.</param> /// <returns>Строка, из которой была удалена метка, если она существовала ранее.</returns> public string HandleLabelAndReturnLine(string line, CompilerEnvironment env) { int colon = line.IndexOf(':'); if (colon == -1) { return(line); } string label = line.Substring(0, colon); if (!CompilerSupport.CheckIdentifierName(label)) { throw new CompilationErrorExcepton($"Имя метки {label} некорректно", env.GetCurrentLine()); } if (env.IsIdentifierExist(label)) { throw new CompilationErrorExcepton($"Идентификатор с именем {label} уже существует.", env.GetCurrentLine()); } env.AddAddressLabelToNewCommand(label); return(line.Substring(colon + 1)); }
private static void IN(string[] args, CompilerEnvironment env) { if (args.Length == 0) { var array = new BitArray(8) { [4] = true }; env.SetByte(array); env.SetByte(new BitArray(8)); return; } if (args.Length > 0) { throw new CompilationErrorExcepton("Команда IN не может принимать более 1 аргумента.", env.GetCurrentLine()); } var dataResponse = GetBitArrays(args, env); env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static void SUBB(string[] args, CompilerEnvironment env) { var dataResponse = GetBitArrays(args, "SUBB", env); if (dataResponse.highBitArray[5]) { dataResponse.highBitArray[1] = true; dataResponse.highBitArray[2] = true; dataResponse.highBitArray[3] = true; } else { //Если команда регистровая dataResponse.highBitArray[7] = true; dataResponse.highBitArray[6] = true; dataResponse.highBitArray[5] = true; dataResponse.highBitArray[4] = true; dataResponse.highBitArray[0] = true; } env.SetByte(dataResponse.lowBitArray); env.SetByte(dataResponse.highBitArray); }
private static DataResponse GetBitArrays(string[] args, string op, CompilerEnvironment env) { if (args.Length != 1) { throw new CompilationErrorExcepton($"Команда {op} принимает 1 агрумент.", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new ExtendedBitArray(), highBitArray = new ExtendedBitArray() }; var r = CompilerSupport.ConvertToRegister(args[0]); if (r.HasValue) { if (r.Value.Number > 7) { throw new CompilationErrorExcepton($"Номер регистра не может быть больше 7.", env.GetCurrentLine()); } return(DataResponseFromRegister(args, op, env, dataResponse, r.Value)); } dataResponse.highBitArray[6] = true; dataResponse.highBitArray[5] = true; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; } else { var address = CompilerSupport.ConvertVariableToAddress(args[0], env); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, 8); } return(dataResponse); }
private static DataResponse GetBitArrays(string[] args, string op, CompilerEnvironment env) { if (args.Length < 0 || args.Length > 2) { throw new CompilationErrorExcepton($"Команда {op} принимает 1 или 2 агрумента.", env.GetCurrentLine()); } var dataResponse = new DataResponse { lowBitArray = new BitArray(8), highBitArray = new BitArray(8) }; var r = CompilerSupport.ConvertToRegister(args[0]); if (r.HasValue) { return(DataResponseFromRegister(args, op, env, dataResponse, r.Value)); } if (args.Length == 2) { throw new CompilationErrorExcepton($"При работе с оперативной памятью команда {op} принимает только 1 аргумент", env.GetCurrentLine()); } dataResponse.highBitArray[6] = true; dataResponse.highBitArray[5] = true; if (args[0][0] == '#') { int num = CompilerSupport.ConvertToInt(args[0].Substring(1)); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, num, Constants.ShortAddressBitsCount); dataResponse.highBitArray[4] = true; } else { var address = CompilerSupport.ConvertVariableToAddress(args[0], env); CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, address, 8); } return(dataResponse); }
private static void MOV(string[] args, CompilerEnvironment env) { if (args.Length != 2) { throw new CompilationErrorExcepton("Оператор MOV должен принимать 2 аргументa.", env.GetCurrentLine()); } var r1 = CompilerSupport.ConvertToRegister(args[0]); var r2 = CompilerSupport.ConvertToRegister(args[1]); if (!r1.HasValue || !r2.HasValue) { throw new CompilationErrorExcepton("Аргументом должен быть регистр.", env.GetCurrentLine()); } var registr1 = r1.Value; var registr2 = r2.Value; if (!registr1.IsDirect || !registr2.IsDirect) { throw new CompilationErrorExcepton("Адресация регистра должна быть прямой.", env.GetCurrentLine()); } var highBitArray = new BitArray(8) { [6] = true, [4] = true, [3] = true, [2] = true, [1] = true, [0] = true }; var lowBitArray = new BitArray(8); CompilerSupport.FillBitArray(null, lowBitArray, (registr2.Number << 4) + registr1.Number, 8); env.SetByte(lowBitArray); env.SetByte(highBitArray); }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line.Substring(1).ToLower().StartsWith("org")) { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /org должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && line[2] != 'B' && line[2] != 'b' && line[2] != 'W' && line[2] != 'w') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'B' || line[2] == 'b')) //работа дерективы .db { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); int address = CompilerSupport.ConvertLabelToFarAddress(value, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, value); } } } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'W' || line[2] == 'w')) //работа дерективы .dw { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); List <string> parameters = new List <string>(); if (value.StartsWith("0x") && value.Length > 4) //если адрес формата 0xFFFF или 0xFFF, раскладываем на 2 байта { parameters.Add("0x" + value.Substring(value.Length - 2)); parameters.Add(value.Substring(0, value.Length - 2)); } else if (value.StartsWith("0b") && value.Length > 10) //если 0b11..11 (больше 1 байта) { parameters.Add("0b" + value.Substring(value.Length - 8)); parameters.Add(value.Substring(0, value.Length - 8)); } else { parameters.Add(value); //если 0xFF, 0b11111111 или Метка parameters.Add("0x00"); } foreach (var p in parameters) { int address = CompilerSupport.ConvertLabelToFarAddress(p, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, p); } } } } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }
/// <summary> /// Обрабатывает директиву процессора, и изменяет окружение в соответствии с ней. /// В случае, если директива некорректна, генерируется <see cref="CompilationErrorExcepton"/> /// </summary> /// <param name="line">Строка кода, из которой извлекается директива.</param> /// <param name="env">Текущее окружение компилятора, которое изменяется в соответствии с директивой.</param> public void HandleDirective(string line, CompilerEnvironment env) { if (line.Substring(1).ToLower().StartsWith("org")) { string[] components = line.Split(' '); if (components.Length != 2) { throw new CompilationErrorExcepton("После /org должно следовать одно число через пробел.", env.GetCurrentLine()); } try { int address = CompilerSupport.ConvertToInt(components[1]); if (address > 255 || address < 0) { throw new Exception(); } env.CurrentAddress = address; } catch (Exception) { throw new CompilationErrorExcepton("Некорректная директива процессора. Адрес должен быть числом в диапазоне от 0 до 255.", env.GetCurrentLine()); } } else if (line[1] == 'C' || line[1] == 'c') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultCodeSegment = segment; } else if (line[1] == 'S' || line[1] == 's') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultStackSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && line[2] != 'B' && line[2] != 'b') { int segment = TryToGetSegmentFromDirecrive(line, env.GetCurrentLine()); env.DefaultDataSegment = segment; } else if ((line[1] == 'D' || line[1] == 'd') && (line[2] == 'B' || line[2] == 'b')) { string values = line.Substring(3); string[] components = values.Split(','); foreach (var i in components) { string value = i.Trim(); int address = CompilerSupport.ConvertLabelToFarAddress(value, env); if (address != -1) { address = address & 0xFF; env.SetByte(new ExtendedBitArray(address)); } else { env.SetCommandWithoutLabel(new CompilerEnvironment.MemoryForLabel { HighBitArray = new ExtendedBitArray(), LowBitArray = new ExtendedBitArray(), Address = env.CurrentAddress, SingleByte = true }, value); } } } else { throw new CompilationErrorExcepton("Некорректная директива процессора.", env.GetCurrentLine()); } }
//Прямая - 000 //@R - 100 //@R+ - 001 //+@R - 101 //@R- - 011 //-@R - 111 private static DataResponse DataResponseFromRegister(string[] args, string op, CompilerEnvironment env, DataResponse dataResponse, CompilerSupport.Register register) { dataResponse.highBitArray[6] = true; dataResponse.highBitArray[4] = true; CompilerSupport.FillBitArray(null, dataResponse.lowBitArray, register.Number, 4); if (register.IsDirect) { //Ничего не делаем } else if (!register.IsChange) { dataResponse.lowBitArray[4] = true; } else if (register.IsPostchange && register.IsIncrement) { dataResponse.lowBitArray[6] = true; } else if (register.IsPostchange) { dataResponse.lowBitArray[5] = true; dataResponse.lowBitArray[6] = true; } else if (register.IsIncrement) { dataResponse.lowBitArray[6] = true; dataResponse.lowBitArray[4] = true; } else { dataResponse.lowBitArray[6] = true; dataResponse.lowBitArray[5] = true; dataResponse.lowBitArray[4] = true; } if (args.Length != 2) { return(dataResponse); } if (args[1] == "1") { dataResponse.lowBitArray[7] = true; return(dataResponse); } if (args[1] != "0") { throw new CompilationErrorExcepton($"Вторым аргументом у команды {op} может быть только 0 или 1.", env.GetCurrentLine()); } return(dataResponse); }
private static void FillAddressAndSetCommand(BitArray highBitArray, BitArray lowBitArray, string label, CompilerEnvironment env) { int address = CompilerSupport.ConvertLabelToFarAddress(label, env); if (address == -1) { var memoryForLabel = new CompilerEnvironment.MemoryForLabel { HighBitArray = highBitArray, LowBitArray = lowBitArray, Address = env.CurrentAddress }; env.SetCommandWithoutLabel(memoryForLabel, label); return; } CompilerSupport.FillBitArray(highBitArray, lowBitArray, address, Constants.FarAddressBitsCount); env.SetByte(lowBitArray); env.SetByte(highBitArray); }