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); }
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); }
/// <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()); } }