Разработка и оптимизация программного обеспечения для УУМ-32
Концепция универсальной учебной машины УУМ-32. Требования к программным и аппаратным средствам. Реализация программного обеспечения. Описание приложения "Макроассемблер для УУМ-32". Стадии и этапы разработки. Функциональное назначение приложения.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 26.11.2014 |
Размер файла | 1,5 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
private string GetAbsolutePathFromCurrent(string path) {
return PathFinder.GetAbsolutePath(this.selfExeFile, path);
}
private int StartCompilation() {
MDIForm activeChild = (MDIForm)this.ActiveMdiChild;
if (activeChild == null) {
throw new Exception("Невозможно вызвать компилятор, так как ни одно окно не активно");
}
if (activeChild.IsChanged) {
if (MessageBox.Show("Исходный текст программы " + activeChild.ProgramName + " был изменен. Будет выполенено сохранение текста программы. Продолжить?\nВыберите \"Нет\", если хотите вернуться и сохранить программу под другим именем", "Требуется сохранение", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation)
== System.Windows.Forms.DialogResult.No) return 1;
}
this.saveToolStripMenuItem_Click(this, new EventArgs());
if (activeChild.AssociatedFileName == null) return 1; // пользователь нажал "Отмена" в диалоге сохранения нового файла
this.c_txtOutput.Text = "*** Компиляция ***\r\n"; // было: this.extAppsStdOutput.Enqueue("*** Компиляция ***"); - но надо не в очередь, а напрямую, т.к. при новой компиляции окно вывода следует очистить. Ну и сразу записали, что начали компиляцию.
this.errorsDataGridView.Rows.Clear();
// приступаем к компиляции
string compilerKey = Enum.GetName(typeof(ExternalApplications), ExternalApplications.Compiler);
int exitCode = this.RunExternalApplication(ExternalApplications.Compiler, CLArgsMaskParser.Parse(this.externalApplicationInfoCollection[compilerKey].ArgumentsMask, activeChild.AssociatedFileName), true);
if (exitCode != 0) {
MessageBox.Show(string.Format("Не удалость скомпилировать {0}\nПодробности см. в окне \"Вывод\"", activeChild.ProgramName), "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return exitCode;
}
private void startCompilationToolStripMenuItem_Click(object sender, EventArgs e) {
this.StartCompilation();
}
private void debugToolStripMenuItem_Click(object sender, EventArgs e) {
//MessageBox.Show("Заглушка запуска отладчика");
this.RunProgram(true);
}
private void compileAndRunToolStripMenuItem_Click(object sender, EventArgs e) {
this.RunProgram();
}
/// <summary>Запускает программу на выполнение заданном режиме</summary>
/// <param name="debug">Параметр, определяющий, следует ли запускать программу в режиме отладки</param>
private void RunProgram(bool debug = false) {
MDIForm activeChild = (MDIForm)this.ActiveMdiChild;
if (activeChild == null) {
return;
}
int exitCode = this.StartCompilation();
if (exitCode == 0) {
string linkerKey = Enum.GetName(typeof(ExternalApplications), ExternalApplications.Linker);
//exitCode = this.StartProcess(this.externalApplicationInfoCollection[linkerKey].ExeFileName, CLArgsMaskParser.Parse(this.externalApplicationInfoCollection[linkerKey].ArgumentsMask, activeChild.AssociatedFileName));
//this.c_txtOutput.Text += "*** Компоновка ***\r\n";
this.extAppsStdOutput.Enqueue("*** Компоновка ***");
exitCode = this.RunExternalApplication(ExternalApplications.Linker, CLArgsMaskParser.Parse(this.externalApplicationInfoCollection[linkerKey].ArgumentsMask, activeChild.AssociatedFileName), true);
if (exitCode == 0) {
ExternalApplications extApp = (debug)? ExternalApplications.Debugger : ExternalApplications.UUM32;
string key = Enum.GetName(typeof(ExternalApplications), extApp);
//this.StartProcess(this.externalApplicationInfoCollection[uumKey].ExeFileName, CLArgsMaskParser.Parse(this.externalApplicationInfoCollection[uumKey].ArgumentsMask, activeChild.AssociatedFileName));
//this.c_txtOutput.Text += "*** Запуск ***\r\n";
this.extAppsStdOutput.Enqueue("*** Запуск ***");
exitCode = this.RunExternalApplication(extApp, CLArgsMaskParser.Parse(this.externalApplicationInfoCollection[key].ArgumentsMask, activeChild.AssociatedFileName));
if (exitCode == 0) {
this.extAppsStdOutput.Enqueue("Программа успешно отработала.");//this.c_txtOutput.Text += "Программа успешно отработала.";
}
else {
this.extAppsStdOutput.Enqueue("Программа завершила работу некорректно. Код возврата: " + exitCode);//this.c_txtOutput.Text += "Программа завершила работу некорректно.";
}
}
else {
MessageBox.Show(string.Format("Не удалость скомпоновать {0}\nПодробности см. в окне \"Вывод\"", activeChild.ProgramName), "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
//-------------------------------------------------------------------------------------------
private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
AboutBox about = new AboutBox();
about.ShowDialog();
about.Dispose();
}
private void MainForm_DragEnter(object sender, DragEventArgs e) {
if (!e.Data.GetDataPresent(DataFormats.FileDrop)) {
e.Effect = DragDropEffects.None;
}
else {
e.Effect = DragDropEffects.Copy;
}
}
// данный обработчик обслуживает и главную форму, и дочерние
private void MainForm_DragDrop(object sender, DragEventArgs e) {
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
foreach (string fName in (string[])e.Data.GetData(DataFormats.FileDrop)) {
if (Path.HasExtension(fName)) { // чтобы не давать открыть папку // TODO: возможно, было бы неплохо проверять и тип файла
this.OpenFile(fName);
}
}
}
}
private void highlightToolStripMenuItem_Click(object sender, EventArgs e) {
FontStyleSettingsForm fontStyler = new FontStyleSettingsForm();
fontStyler.BaseFont = (Font)this.childStyleSettings.BaseFont.Clone();
fontStyler.StylesEnabled = this.childStyleSettings.FontStylesEnabled;
fontStyler.StandartElementsFontStyles =
Misc.TemplateMethods<FontStyleSettingsForm.TextElementStyle>.GetCloneableListCopy(
this.childStyleSettings.StandartElementsFontStyles
);
fontStyler.KeywordsFontStyles =
Misc.TemplateMethods<FontStyleSettingsForm.TextElementStyle>.GetCloneableListCopy(
this.childStyleSettings.KeywordsFontStyles
);
fontStyler.BackgroundColor = this.childStyleSettings.BackgroundColor;
fontStyler.RunAsmBeforeShellStart = this.childStyleSettings.RunAsmBeforeShellStart;
fontStyler.AsmCommandLineArgument = this.childStyleSettings.AsmCommandlineArgument;
fontStyler.IsRelativePaths = this.allPathsAreRelative;
fontStyler.KeywordsFileName = GetAbsolutePathFromCurrent(this.childStyleSettings.KeywordsFileName);
if (fontStyler.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
this.childStyleSettings.BaseFont = fontStyler.BaseFont;
this.childStyleSettings.FontStylesEnabled = fontStyler.StylesEnabled;
this.childStyleSettings.StandartElementsFontStyles = fontStyler.StandartElementsFontStyles;
this.childStyleSettings.KeywordsFontStyles = fontStyler.KeywordsFontStyles;
this.childStyleSettings.BackgroundColor = fontStyler.BackgroundColor;
this.childStyleSettings.RunAsmBeforeShellStart = fontStyler.RunAsmBeforeShellStart;
this.childStyleSettings.AsmCommandlineArgument = fontStyler.AsmCommandLineArgument;
this.childStyleSettings.KeywordsFileName = GetCurrentPathFromAbsolute(fontStyler.KeywordsFileName);
this.applyChildrenSettings();
}
fontStyler.Dispose();
}
private void externalAppsSettingsToolStripMenuItem_Click(object sender, EventArgs e) {
ExternalAppsSettingsForm extAppsConfigurator = new ExternalAppsSettingsForm(this.allPathsAreRelative);
ExternalApplications[] externalApplications = (ExternalApplications[])Enum.GetValues(typeof(ExternalApplications));
foreach (ExternalApplications extApp in externalApplications) {
string key = Enum.GetName(typeof(ExternalApplications), extApp);
string exe = this.GetAbsolutePathFromCurrent(this.externalApplicationInfoCollection[key].ExeFileName);
extAppsConfigurator.SetApplicationName(extApp, exe);
extAppsConfigurator.SetArgumentsMask(extApp, this.externalApplicationInfoCollection[key].ArgumentsMask);
}
if (extAppsConfigurator.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
this.allPathsAreRelative = extAppsConfigurator.UseRelativePaths;
foreach (ExternalApplications extApp in externalApplications) {
string key = Enum.GetName(typeof(ExternalApplications), extApp);
string exe = GetCurrentPathFromAbsolute(extAppsConfigurator.GetApplicationName(extApp));
this.externalApplicationInfoCollection[key] = new ExternalApplicationInfo(exe, extAppsConfigurator.GetArgumentsMask(extApp));
}
this.SaveSettingsToXML();
}
extAppsConfigurator.Dispose();
}
private void linesNumerationToolStripMenuItem_Click(object sender, EventArgs e) {
LineNumerationSettingsForm numerationEditor = new LineNumerationSettingsForm(this.ChildNumerationSettings);
if (numerationEditor.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
this.ChildNumerationSettings = new MDIForm.NumerationSetting(numerationEditor.NumerationNeed, numerationEditor.NumeratorForeColor, numerationEditor.NumeratorBackColor);
}
numerationEditor.Dispose();
}
private void c_txtOutput_TextChanged(object sender, EventArgs e) {
c_lblFocusCatcher.Focus();
c_txtOutput.SelectionStart = c_txtOutput.TextLength;
c_txtOutput.ScrollToCaret();
c_txtOutput.Refresh();
}
private void c_txtOutput_DoubleClick(object sender, EventArgs e) {
int curLine = c_txtOutput.GetLineFromCharIndex(c_txtOutput.GetFirstCharIndexOfCurrentLine());
string line = c_txtOutput.Lines[curLine].Trim().ToLower();
if (line.StartsWith("строка")) { // TODO: убрать константу, синхронизовать с ассемблером, т.к. сообщения формирует он
line = line.Replace("строка", "").Trim();
int ddot = line.IndexOf(':');
int lineNum = int.Parse(line.Substring(0, ddot)) - 1;
((MDIForm)this.ActiveMdiChild).JumpToLine(lineNum);
}
}
private void clearTxtOutToolStripMenuItem_Click(object sender, EventArgs e) {
this.c_txtOutput.Clear();
}
private void c_tmrExtAppsStdOutputDequeuer_Tick(object sender, EventArgs e) {
while (this.extAppsStdOutput.Count != 0) {
this.c_txtOutput.Text += this.extAppsStdOutput.Dequeue() + Environment.NewLine;
}
XmlDocument doc = new XmlDocument();
while (this.extAppsStdError.Count != 0) {
string text = this.extAppsStdError.Dequeue();
if (text != null) {
try {
doc.LoadXml(text);
XmlElement el = doc.DocumentElement;
this.errorsDataGridView.Rows.Add();
DataGridViewRow row = this.errorsDataGridView.Rows[this.errorsDataGridView.Rows.Count - 1];
row.Cells["ColumnFileName"].Value = el.Attributes["file"].Value;
row.Cells["ColumnLineNumber"].Value = el.Attributes["line"].Value;
row.Cells["ColumnErrorDescription"].Value = el.Attributes["description"].Value;
}
catch { }
}
}
}
private void errorsDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e) {
try {
DataGridViewRow row = this.errorsDataGridView.Rows[e.RowIndex];
string fileName = (string)row.Cells["ColumnFileName"].Value;
if (!string.IsNullOrEmpty(fileName)) {
MDIForm mdi = this.OpenFile(fileName);
string line = (string)row.Cells["ColumnLineNumber"].Value;
if (!string.IsNullOrEmpty(line)) {
int l = int.Parse(line) - 1;
mdi.JumpToLine(l);
}
}
}
catch { }
}
}
}
Приложение 9. Фрагмент исходного кода приложения «Макроассемблер для УУМ-32». Код класса, представляющего контрольную секцию программы
Файл "Sect\ControlSection.cs"
using System;
using System.Collections.Generic;
using UUM32Asm.Asm;
using UUM32Asm.Cmd;
using UUM32Asm.FileWriters;
using UUM32Asm.MachineCommands;
using UUM32Asm.Operands;
using UUM32Asm.PassLines;
using UUM32Asm.Tables;
namespace UUM32Asm.Section
{
/// <summary>Представляет управляющую секцию.</summary>
class ControlSection
{
/// <summary>Возвращает имя данной управляющей секции.</summary>
public string Name { get; private set; }
/// <summary>Возвращает список программных блоков данной управляющей секции.</summary>
public List<ProgramBlock> Blocks { get; private set; }
/// <summary>Возвращает имя файла, в котором объявлена данная секция.</summary>
public string FileName { get; private set; }
/// <summary>Таблица операций ассемблера.</summary>
OpTab opTab;
/// <summary>Таблица имен данной управляющей секции.</summary>
SymTab symTab;
/// <summary>Таблица изначальных и переопределенных в данной управляющей секции имен регистров.</summary>
SymTab regTab;
/// <summary>Очередь, содержащая экземпляры класса SecondPassLine с расширенной информацией о каждой строке программы. Требуется для второго просмотра.</summary>
Queue<SecondPassLine> firstPassOutQueue;
/// <summary>Список, содержащий элементы, необходимые для промежуточного просмотра</summary>
List<IntermediatePassLine> imPassList;
/// <summary>Список, содержащий строки, необходимые для рассчета неопределенных во время первого прохода констант</summary>
List<SecondPassLine> linesWithConstantsList;
/// <summary>Длина данной управляющей секции.</summary>
uint sectionLength; //TODO: потом все uint'ы сменить на int
/// <summary>Список внешних имен, которые следует импортировать в данную секцию</summary>
List<SymTabEl> importedNames;
/// <summary>Инициализирует новый экземпляр класса ControlSection с заданным именем.</summary>
/// <param name="name">Строка, задающая имя управляющей секции.</param>
public ControlSection(string name, string fileName)
{
this.Name = name;
this.FileName = fileName;
this.Blocks = new List<ProgramBlock>();
this.importedNames = new List<SymTabEl>();
}
/// <summary>Добавляет строку в определенный программный блок данной секции.</summary>
/// <param name="pl">Структура, содержащая информацию о строке программы.</param>
/// <param name="blockName">Имя блока, в который будет добавляться строка. Если не задано, строка добавляется в блок по умолчанию (есть в любой секции). Если блока с заданным именем не существует, он будет создан.</param>
public void AddCodeLine(PassLine pl, string blockName = "")
{
ProgramBlock currentBlock = null;
foreach (ProgramBlock blk in Blocks) // проверяем, существует ли блок с таким именем
{
if (blk.Name == blockName)
{
currentBlock = blk;
break;
}
}
if (currentBlock == null)
{
currentBlock = new ProgramBlock(blockName);
Blocks.Add(currentBlock);
}
currentBlock.AddCodeLine(pl);
}
/// <summary>Добавляет строку с директивой END в последний блок данной секции.</summary>
/// <param name="pl">Структура, содержащая информацию о строке программы.</param>
public void AddEndLine(PassLine pl)
{
Blocks[Blocks.Count - 1].AddCodeLine(pl);
}
/// <summary>Транслирует данную управляющую секцию в объектный код и выдает листинг.</summary>
/// <param name="optab">Таблица операций ассемблера.</param>
/// <param name="initRegTab">Исходная таблица регистров ассемблера.</param>
/// <param name="errorList">Список, содержащий сообщения об ошибках, возникших в ходе работы ассемблера.</param> // <param name="errorLog">Очередь, содержащая сообщения об ошибках, возникших в ходе работы ассемблера.</param>
/// <param name="lstFile">Экземпляр класса LstFileWriter для записи листинга.</param>
/// <param name="objFile">Экземпляр класса ObjFileWriter для записи объектного кода программы.</param>
public void Translate(OpTab optab, SymTab initRegTab, /*Queue<string> errorLog*/List<CompileError> errorList, LstFileWriter lstFile, ObjFileWriter objFile) {
opTab = optab;
regTab = new SymTab(initRegTab);
symTab = new SymTab();
int errorCount = /*errorLog*/errorList.Count; // т.к. лог ошибок общий, запомним, сколько ошибок было до нашей секции, и если после первого прохода это число не изменится, пойдем на следующие проходы
FirstPass(/*errorLog*/errorList);
if (/*errorLog*/errorList.Count != errorCount) {
}
else {
IntermediatePass(/*errorLog*/errorList);
if (/*errorLog*/errorList.Count != errorCount) {
}
else {
CalculateConstants(/*errorLog*/errorList);
if (/*errorLog*/errorList.Count != errorCount) {
}
else {
SecondPass(lstFile, objFile, /*errorLog*/errorList);
}
}
}
}
/// <summary>Возвращает список всех команд секции, упорядоченный по блокам (сначала инструкции 1го блока, затем 2го и т.д.).</summary>
/// <returns>Результат - список экземпляров класса PassLine.</returns>
private List<PassLine> GetCode()
{
int n = 0;
foreach (ProgramBlock block in Blocks)
n += block.Code.Count;
List<PassLine> res = new List<PassLine>(n);
foreach (ProgramBlock block in Blocks)
res.AddRange(block.Code);
return res;
}
/// <summary>Первый проход трансляции.</summary>
/// <param name="errorList">Список, содержащий информацию об ошибках, возникших в ходе работы ассемблера</param> // /// <param name="errorLog">Очередь, содержащая сообщения об ошибках, возникших в ходе работы ассемблера.</param>
void FirstPass(/*Queue<string> errorLog*/List<CompileError> errorList)
{
/// <summary>Счетчик размещений данной управляющей секции.</summary>
uint locCtr;
/// <summary>Начальный адрес данной управляющей секции.</summary>
uint startAddr;
firstPassOutQueue = new Queue<SecondPassLine>();
imPassList = new List<IntermediatePassLine>();
linesWithConstantsList = new List<SecondPassLine>();
List<PassLine> code = this.GetCode();
PassLine line = code[0];
try {
NumberOperand numOp = new NumberOperand(line.Operands);
locCtr = startAddr = numOp.Value;
}
catch (OperandException e) {
errorList.Add(/*new CompileError(line.LineNumber, e.Message)*/this.GetCompilerErrorUseMetadata(line, e.Message));
locCtr = startAddr = 0;
}
for (int i = 0; i < code.Count; i++) {
line = code[i];
SecondPassLine spLine = new SecondPassLine(line, locCtr);
if (line.Label != String.Empty && line.OpCode != AsmDirectives.Alias) {
if (symTab.Contains(line.Label)) {
errorList.Add(/*new CompileError(line.LineNumber, string.Format("Повторное опеределение метки \"{0}\".", line.Label))*/this.GetCompilerErrorUseMetadata(line, string.Format("Повторное опеределение метки \"{0}\".", line.Label)));
}
else if (regTab.Contains(line.Label)) {
errorList.Add(/*new CompileError(line.LineNumber, string.Format("Недопустимое имя метки \"{0}\" - это имя зарезервировано для регистра.", line.Label))*/this.GetCompilerErrorUseMetadata(line, string.Format("Недопустимое имя метки \"{0}\" - это имя зарезервировано для регистра.", line.Label)));
}
else {
try {
symTab.Add(new SymTabEl(line.Label, locCtr));
}
catch (SymTabException e) {
errorList.Add(/*new CompileError(line.LineNumber, e.Message)*/this.GetCompilerErrorUseMetadata(line, e.Message));
}
}
}
if (line.OpCode != String.Empty) {
switch (line.OpCode) {
case AsmDirectives.Start: case AsmDirectives.End: case AsmDirectives.CSect: case AsmDirectives.Export: {
// все эти директивы обрабатываются не в этом проходе
break;
}
case AsmDirectives.Import: {
// импортируемые имена добавляем в первом проходе, т.к. они могут потребоваться уже в промежуточном проходе
try {
NameListOperand nlstOp = new NameListOperand(line.Operands);
foreach (string name in nlstOp.NameList) {
SymTabEl ste = symTab.Find(name);
if (ste != null) {
//errorLog.Enqueue(string.Format("Строка {0}: Невозможно импортировать имя \"{1}\" в секцию {2}. Метка с таким именем уже объявлена в данной секции.", line.LineNumber, name, this.Name)); //TODO: эта ошибка накладывается на исключение ArgumentException класса ImportNamesRec, выбрасываемое при добавлении одинаковых имен
errorList.Add(this.GetCompilerErrorUseMetadata(line, string.Format("Невозможно импортировать имя \"{0}\" в секцию \"{1}\". Метка с таким именем уже объявлена в данной секции.", name, this.Name))/*new CompileError(line.LineNumber, string.Format("Невозможно импортировать имя \"{0}\" в секцию \"{1}\". Метка с таким именем уже объявлена в данной секции.", name, this.Name))*/); //TODO: эта ошибка накладывается на исключение ArgumentException класса ImportNamesRec, выбрасываемое при добавлении одинаковых имен
}
else if (regTab.Contains(name)) {
//errorLog.Enqueue(string.Format("Строка {0}: Невозможно импортировать имя \"{1}\" в секцию {2}. Имя совпадает с одним из регистров.", line.LineNumber, name, this.Name));
errorList.Add(this.GetCompilerErrorUseMetadata(line, string.Format("Невозможно импортировать имя \"{0}\" в секцию \"{1}\". Имя зарезервировано для одного из регистров.", name, this.Name))/*new CompileError(line.LineNumber, string.Format("Невозможно импортировать имя \"{0}\" в секцию \"{1}\". Имя зарезервировано для одного из регистров.", name, this.Name))*/);
}
else {
SymTabEl imported = new SymTabEl(name, 0);
imported.Imported = true;
symTab.Add(imported);
importedNames.Add(imported); // во втором проходе содержимое этого списка запишется в объектный файл
}
}
break;
}
catch (ArgumentException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
catch /*(Exception e)*/ {
throw;
}
break;
}
case AsmDirectives.ResB: case AsmDirectives.ResH: case AsmDirectives.ResW: {
try {
NumberOperand nOp = new NumberOperand(line.Operands);
spLine.Op = nOp;
byte k = AsmDirectives.SizeOfType(line.OpCode);
locCtr += nOp.Value * k;
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
break;
}
case AsmDirectives.Byte: case AsmDirectives.Half: case AsmDirectives.Word: {
linesWithConstantsList.Add(spLine);
try { // исключение возникнет, если строка-инициализатор массива содержала пустые элементы (например: 1, 2, , 4, 5)
locCtr += (uint)ConstantOperand.CalculateArraySize(spLine.FirstPassLine.Operands, (ConstantType)AsmDirectives.SizeOfType(spLine.FirstPassLine.OpCode));
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
break;
}
case AsmDirectives.Equate: {
if (!string.IsNullOrEmpty(line.Label)/*line.Label != String.Empty*/) { // если при директиве Equate есть метка, то все в порядке - она ранее была добавлена в таблицу имен
SymTabEl el = symTab.Find(line.Label); // TODO: на всякий отследить отсутствие элемента в SymTab
el.Undefined = true; // отметили, что данная запись таблицы имен является неопределенной
imPassList.Add(new IntermediatePassLine(spLine, el)); // запомнили строку с директивой Equate для промежуточного просмотра
}
else {
errorList.Add(this.GetCompilerErrorUseMetadata(line, string.Format("Директива {0} без метки.", AsmDirectives.Equate))/*new CompileError(line.LineNumber, string.Format("Директива {0} без метки.", AsmDirectives.Equate))*/);
}
// locCtr увеличивать не требуется
break;
}
case AsmDirectives.Alias: {
try {
if (string.IsNullOrEmpty(line.Label)) {
throw new UUM32AsmException(string.Format("Директива {0} без метки", AsmDirectives.Alias));
}
else if (regTab.Contains(line.Label)) {
throw new UUM32AsmException(string.Format("Имя \"{0}\" совпадает со стандартным именем одного из регистров либо было объявлено ранее", line.Label));
}
NameOperand nop = new NameOperand(spLine.FirstPassLine.Operands);
SymTabEl reg = regTab.Find(nop.Name);
if (reg != null) {
regTab.Add(new SymTabEl(line.Label, reg.Address));
}
else {
throw new UUM32AsmException(string.Format("Регистра с именем \"{0}\" не существует", nop.Name));
}
}
catch (UUM32AsmException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
catch (ArgumentException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
break;
}
case MacroAsm.MacroAssembler.Directives.Include:
case MacroAsm.MacroAssembler.Directives.MacroStart:
case MacroAsm.MacroAssembler.Directives.MacroEnd: {
errorList.Add(this.GetCompilerErrorUseMetadata(line, string.Format("Директиву \"{0}\" можно использовать только в макрокоде. Смените расширение файла на \"{1}\"", line.OpCode, FileExtensions.MacroassemblerSourceFileExtension))/*new CompileError(line.LineNumber, string.Format("Директиву \"{0}\" можно использовать только в макрокоде. Смените расширение файла на \"{1}\"", line.OpCode, FileExtensions.MacroassemblerSourceFileExtension))*/);
break;
}
default: {
try {
Command cmd = new Command(line.OpCode, opTab);
locCtr += cmd.Size;
}
catch (CommandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(line, e.Message)/*new CompileError(line.LineNumber, e.Message)*/);
}
break;
}
}
}
firstPassOutQueue.Enqueue(spLine);
}
sectionLength = locCtr - startAddr;
}
/// <summary>Выполняет промежуточный проход трансляции.</summary>
/// <param name="errorList">Список, содержащий информацию об ошибках, возникших в ходе работы ассемблера</param> // /// <param name="errorLog">Очередь, содержащая сообщения об ошибках, возникших в ходе работы ассемблера.</param>
void IntermediatePass(/*Queue<string> errorLog*/List<CompileError> errorList) {
foreach (IntermediatePassLine imLine in imPassList) {
try {
imLine.Recalculate(imPassList, symTab);
if (imLine.ContainsImportedNames) {
throw new OperandException(string.Format("Директива {0} не может оперировать с импортированными именами, так как на этапе компиляции значения этих имен неопределены.", AsmDirectives.Equate));
}
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(imLine.SecPassLine.FirstPassLine, e.Message)/*new CompileError(imLine.SecPassLine.FirstPassLine.LineNumber, e.Message)*/);
}
catch (Exception e) { // TODO: разобраться с типом исключения
errorList.Add(this.GetCompilerErrorUseMetadata(imLine.SecPassLine.FirstPassLine, string.Format("Неизвестная ошибка: {0}", e.Message))/*new CompileError(imLine.SecPassLine.FirstPassLine.LineNumber, string.Format("Неизвестная ошибка: {0}", e.Message))*/); //TODO: отредактировать строку сообщения и сменить его тип после отладки
}
}
foreach (IntermediatePassLine imLine in imPassList) { // теперь проверим, все ли записи определены
if (imLine.UndefinedElementsCount > 0) {
errorList.Add(this.GetCompilerErrorUseMetadata(imLine.SecPassLine.FirstPassLine, string.Format("Невозможно связать имя \"{1}\" со значением выражения \"{0}\". Проверьте выражения на рекурсию.", imLine.SecPassLine.FirstPassLine.Operands, imLine.SecPassLine.FirstPassLine.Label))/*new CompileError(imLine.SecPassLine.FirstPassLine.LineNumber, string.Format("Невозможно связать имя \"{1}\" со значением выражения \"{0}\". Проверьте выражения на рекурсию.", imLine.SecPassLine.FirstPassLine.Operands, imLine.SecPassLine.FirstPassLine.Label))*/);
}
}
}
/// <summary>Выполняет вычисление числовых значений констант, неопределенных во время первого прохода по причине участия в формировании константы неопределенного имени (метки директивы Equate)</summary>
/// <param name="errorList">Список, содержащий информацию об ошибках, возникших в ходе работы ассемблера</param> // /// <param name="errorLog">Очередь, содержащая сообщения об ошибках, возникших в ходе работы ассемблера.</param>
void CalculateConstants(/*Queue<string> errorLog*/List<CompileError> errorList) {
foreach (SecondPassLine spLine in this.linesWithConstantsList) {
try {
ConstantType ct = (ConstantType)AsmDirectives.SizeOfType(spLine.FirstPassLine.OpCode);
ConstantOperand cOp = new ConstantOperand(spLine.FirstPassLine.Operands, ct, symTab, spLine.Addr);
if (cOp.Undefined) {
throw new OperandException("Невозможно вычислить значение, задающее константу");
}
spLine.Op = cOp;
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(spLine.FirstPassLine, e.Message)/*new CompileError(spLine.FirstPassLine.LineNumber, e.Message)*/);
}
}
}
/// <summary>Выполняет второй проход трансляции.</summary>
/// <param name="lstFile">Ссылка на экземпляр класса LstFileWriter для записи листинга.</param>
/// <param name="objFile">Ссылка на экземпляр класса ObjFileWriter для записи объектного кода программы.</param>
/// <param name="errorList">Список, содержащий информацию об ошибках, возникших в ходе работы ассемблера</param> // /// <param name="errorLog">Ссылка на очередь, содержащую сообщения об ошибках, возникших в ходе работы ассемблера.</param>
void SecondPass(LstFileWriter lstFile, ObjFileWriter objFile, /*Queue<string> errorLog*/List<CompileError> errorList) {
List<byte> objCode = null;
SecondPassLine spLine = firstPassOutQueue.Dequeue();
lstFile.WriteLine(spLine, null);
objFile.AddHeaderRec(spLine.FirstPassLine.Label, sectionLength);
while (firstPassOutQueue.Count > 0/*spLine.FirstPassLine.OpCode != AsmDirectives.End*/) {
spLine = firstPassOutQueue.Dequeue();
PassLine fpLine = spLine.FirstPassLine;
MachineCommand machineCommand = null;
ObjFileWriter.BodyRecTypes bodyRecType = ObjFileWriter.BodyRecTypes.Code; // нужна для разбиения obj-файла на строки код/данные
objCode = null;
if (AsmDirectives.IsAsmDirective(fpLine.OpCode)) {
if (AsmDirectives.IsConstantDirective(fpLine.OpCode)) { //(fpLine.OpCode == AsmDirectives.Byte || fpLine.OpCode == AsmDirectives.Half || fpLine.OpCode == AsmDirectives.Word)
objCode = ((ConstantOperand)spLine.Op/*Constant*/).ByteList;
bodyRecType = ObjFileWriter.BodyRecTypes.Data;
objFile.AddToBodyRec(objCode, bodyRecType); // TODO: если захочешь вернуться к старому варианту, когда объ код добавлялся после блока else этого if'а, закомменть эту строку, строку добавления объ кода ветви else и раскомменть строку добавления объ кода после блока else
}
else if (AsmDirectives.IsResDirective(fpLine.OpCode)) {
objFile.StartNewBodyRec(((NumberOperand)spLine.Op).Value * AsmDirectives.SizeOfType(fpLine.OpCode));
}
else if (fpLine.OpCode == AsmDirectives.Export) {
try {
NameListOperand nlstOp = new NameListOperand(fpLine.Operands);
foreach (string name in nlstOp.NameList) {
SymTabEl ste = symTab.Find(name);
if (ste != null) {
// TODO: оказывается, имя секции не экспортируется автоматически
objFile.AddToCurrentExpNamesRec(ste);
}
else {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, string.Format("Невозможно экспортировать имя \"{0}\" из секции {1}. Не найдено объявление данного имени.", name, this.Name))/*new CompileError(fpLine.LineNumber, string.Format("Невозможно экспортировать имя \"{0}\" из секции {1}. Не найдено объявление данного имени.", name, this.Name))*/);
}
}
}
catch (ArgumentException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, e.Message)/*new CompileError(fpLine.LineNumber, e.Message)*/);
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, e.Message)/*new CompileError(fpLine.LineNumber, e.Message)*/);
}
catch (Exception e) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, string.Format("Неизвестная ошибка: {0}.", e.Message))/*new CompileError(fpLine.LineNumber, string.Format("Неизвестная ошибка: {0}.", e.Message))*/);
}
}
else if (fpLine.OpCode == AsmDirectives.Import) {
foreach (SymTabEl stel in importedNames) {
objFile.AddToCurrentImpNamesRec(stel.Label);
}
}
}
else if (!fpLine.OpCode.Equals(string.Empty)) { // если строка содержит операцию //if (opTab.Contains(fpLine.OpCode))
Command cmd;
try {
cmd = new Command(fpLine.OpCode, opTab);
}
catch { //TODO: разобраться здесь
throw new UUM32AsmException("Второй проход: нет комнды в OpTab!");
}
// анализ числа операндов
string[] ops = { String.Empty, String.Empty };
switch (cmd.OperandCount) {
case 0:
if (fpLine.Operands != String.Empty) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, string.Format("У команды \"{0}\" не должно быть операндов.", fpLine.OpCode))/*new CompileError(fpLine.LineNumber, string.Format("У команды \"{0}\" не должно быть операндов.", fpLine.OpCode))*/);
}
break;
case 1:
ops[0] = fpLine.Operands;
break;
case 2:
int i = fpLine.Operands.IndexOf(',');
if (i <= 0 || i == (fpLine.Operands.Length - 1)) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, string.Format("У команды \"{0}\" должно быть два операнда.", fpLine.OpCode))/*new CompileError(fpLine.LineNumber, string.Format("У команды \"{0}\" должно быть два операнда.", fpLine.OpCode))*/);
break;
}
ops[0] = fpLine.Operands.Substring(0, i).Trim();
ops[1] = fpLine.Operands.Remove(0, i + 1).Trim();
break;
}
Operand[] Operands = { null, null };
for (int i = 0; i < cmd.OperandCount; i++) {
try {
switch (cmd.Operands[i]) {
case OperandTypes.Number:
try {
Operands[i] = new NumberOperand(ops[i]);
}
catch {
Operands[i] = new NumberOperand();
throw;
}
break;
case OperandTypes.Register:
try {
Operands[i] = new RegisterOperand(ops[i], regTab);
}
catch {
Operands[i] = new RegisterOperand();
throw;
}
break;
case OperandTypes.Memory:
try {
Operands[i] = new AddressOperand(ops[i], symTab, spLine.Addr);
}
catch {
//Operands[i] = new AddressOperand();
Operands[i] = AddressOperand.CreateDummyAddressOperand();
throw;
}
break;
}
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(fpLine, e.Message)/*new CompileError(fpLine.LineNumber, e.Message)*/);
}
}
switch (cmd.Format) {
case 1:
machineCommand = new FirstTypeCommand(cmd.Code, cmd.Eop);
break;
case 2:
if (cmd.Operands[0] == OperandTypes.Register) {
machineCommand = new SecondTypeCommand(cmd.Code, cmd.Eop, (RegisterOperand)Operands[0], (RegisterOperand)Operands[1]);
}
else if (cmd.Operands[0] == OperandTypes.Number) {
machineCommand = new SecondTypeCommand(cmd.Code, cmd.Eop, (NumberOperand)Operands[0]);
}
break;
case 3:
if (cmd.Operands[0] == OperandTypes.Memory) {
machineCommand = new ThirdTypeCommand(cmd, (AddressOperand)Operands[0], spLine.Addr + cmd.Size);
}
else if (cmd.Operands[0] == OperandTypes.Register) {
machineCommand = new ThirdTypeCommand(cmd, (RegisterOperand)Operands[0], (AddressOperand)Operands[1], spLine.Addr + cmd.Size);
}
break;
case 4:
if (cmd.Operands[0] == OperandTypes.Memory) {
machineCommand = new FourthTypeCommand(cmd, (AddressOperand)Operands[0], spLine.Addr + cmd.Size);
}
else if (cmd.Operands[0] == OperandTypes.Register) {
machineCommand = new FourthTypeCommand(cmd, (RegisterOperand)Operands[0], (AddressOperand)Operands[1], spLine.Addr + cmd.Size);
}
break;
}
objCode = machineCommand.GetByteList();
bool bodyRecAdded = false;
if ((cmd.Format == 3 || cmd.Format == 4)) { // для команд 3 и 4 формата при необходимости надо добавить модификаторы
AddressCommand addressMachineCommand = (AddressCommand)machineCommand;
if (addressMachineCommand.NeedsModification) {
objFile.AddToNewBodyRec(objCode); // выносим модифицируюмую запись в отдельную строку, чтобы было легче читать объ. код
bodyRecAdded = true;
foreach (ObjFileWriter.ModifierRec mRec in addressMachineCommand.ModifierRecords) {
objFile.AddModifierRec(mRec);
}
}
}
if (!bodyRecAdded) {
objFile.AddToBodyRec(objCode, bodyRecType);
}
}
else { // строка содержит только метку
;
}
lstFile.WriteLine(spLine, objCode);
}
// если послденяя директива была END, надо определить точку входа
if (spLine.FirstPassLine.OpCode == AsmDirectives.End && spLine.FirstPassLine.Operands != String.Empty) {
try {
AddressOperand op = new AddressOperand(spLine.FirstPassLine.Operands, symTab, spLine.Addr);
objFile.AddEndRec((uint)op.Value);
}
catch (OperandException e) {
errorList.Add(this.GetCompilerErrorUseMetadata(spLine.FirstPassLine, e.Message)/*new CompileError(spLine.FirstPassLine.LineNumber, e.Message)*/);
}
}
else {
objFile.AddEndRec();
}
}
/// <summary>
/// Возвращает ошибку компиляции, по возможности заполняя поля имени файла и номера строки из метаданных макроассемблера, лежащих в заданной строке PassLine.
/// Если метаданных нет, берется текущее имя файла для данной секции, номер строки берется из заданной строки PassLine.
/// </summary>
/// <param name="line"></param>
/// <param name="errorText"></param>
private CompileError GetCompilerErrorUseMetadata(PassLine line, string errorText) {
CompileError err = new CompileError();
err.Description = errorText;
if (!string.IsNullOrEmpty(line.MetaComment)) {
int sepIndex = line.MetaComment.LastIndexOf(PassLine.MetaDataSeparator);
err.FileName = line.MetaComment.Substring(0, sepIndex);
err.LineNumber = int.Parse(line.MetaComment.Substring(sepIndex + 1));
}
else {
err.FileName = this.FileName;
err.LineNumber = line.LineNumber;
}
return err;
}
}
}
Размещено на Allbest.ru
...Подобные документы
Разработка программного обеспечения решения задач численного вычисления определенных интегралов. Анализ задачи, методы, инструменты: требования к аппаратным ресурсам и программным средствам. Руководство пользователя, тестирование приложения, применение.
курсовая работа [1,6 M], добавлен 27.08.2012Область применения и требования создаваемого Web-приложения. Требования к техническому и программному обеспечению. Разработка структуры Web-приложения и выбор средств программной реализации. Программная реализация Web-приложения. Структура базы данных.
дипломная работа [1,4 M], добавлен 03.06.2014Общие сведения о платформе Microsoft NET Framework. Разработка приложения "Поставка и реализация программного обеспечения", содержащего базу данных о каталогах адресов в Internet. Описание логической структуры. Требования к техническому обеспечению.
курсовая работа [2,4 M], добавлен 28.06.2011Возможности среды программирования delphi при разработке приложения с визуальным интерфейсом. Разработка спецификации программного обеспечения и на ее основе кода программного продукта. Отладка программы "трассировкой", ее тестирование и оптимизация.
курсовая работа [501,4 K], добавлен 07.12.2016Цели и задачи программной инженерии. Понятие программного обеспечения. Шесть принципов эффективного использования программного обеспечения. Виды программного обеспечения: общесистемное, сетевое и прикладное. Принципы построения программного обеспечения.
курсовая работа [30,4 K], добавлен 29.06.2010Общая характеристика и функциональное назначение проектируемого программного обеспечения, требования к нему. Разработка и описание интерфейса клиентской и серверной части. Описание алгоритма и программной реализации приложения. Схема базы данных.
курсовая работа [35,4 K], добавлен 12.05.2013Разбиение данных по таблицам и создание связей между таблицами. Нормализация и проектирование сценария работы базы данных. Выбор программного обеспечения. Требования к аппаратным и программным средствам для работы созданного программного продукта.
курсовая работа [30,2 K], добавлен 23.01.2011Возможности среды программирования delphi при разработке приложения с визуальным интерфейсом. Отладка программных модулей с использованием специализированных программных средств. Тестирование программного обеспечения. Оптимизация программного кода.
курсовая работа [974,0 K], добавлен 21.12.2016Требования к программному средству. Спецификация качества программного обеспечения. Требования к эргономике и технической эстетики. Стадии и этапы разработки, порядок контроля и приемки. Проектирование архитектуры приложения, руководство пользователя.
курсовая работа [381,6 K], добавлен 20.06.2012Разработка и реализация демонстрационного многопоточного приложения. Выбор основных средств реализации. Описание логики работы приложения и разработка программного обеспечения. Описание пользовательского интерфейса. Реализация потоков в Delphi.
курсовая работа [462,5 K], добавлен 10.08.2014Проектирование программного модуля: сбор исходных материалов; описание входных и выходных данных; выбор программного обеспечения. Описание типов данных и реализация интерфейса программы. Тестирование программного модуля и разработка справочной системы.
курсовая работа [81,7 K], добавлен 18.08.2014Описание истории развития информационных технологий. Исследование предпочтений по использованию программного обеспечения пользователя персонального компьютера начального уровня и разработка интерфейсного приложения в среде программирования Delphi.
дипломная работа [2,0 M], добавлен 14.01.2012Требования к аппаратным и операционным ресурсам. Логическая и физическая организация. Состав основных классов проекта. Технико-экономическое обоснование разработки программного средства. Задержки при обработке данных. Разработка интерфейса приложения.
дипломная работа [4,4 M], добавлен 16.06.2017Разработка базы данных и прикладного программного приложения с целью обеспечения хранения, накопления и предоставления информации об учащихся МБОУ "Средняя общеобразовательная школа №18" г. Грозный. Методы обеспечения информационной безопасности.
дипломная работа [2,9 M], добавлен 25.06.2015Разработка программного продукта учёта работы предприятия "Зеленстрой". Проектирование предметной области: концептуальное моделирование, интерфейс приложения. Реализация автоматизированной информационной системы, требования к аппаратным средствам.
курсовая работа [679,8 K], добавлен 11.11.2010Архитектура и история создания операционной системы Android. Язык программирования Java. Выбор средства для реализации Android приложения. Программная реализация Android приложения. Проведение тестирования разработанного программного обеспечения.
курсовая работа [167,8 K], добавлен 18.01.2017Практические аспекты использования прикладного программного обеспечения при разработке базы данных "Аудиторный фонд ГБОУ СПО "Старооскольский педагогический колледж". Системы управления базами данных. Описание и функциональные возможности приложения.
курсовая работа [360,4 K], добавлен 07.10.2014Этапы разработки программного приложения, выполняющего синтаксический анализ программы на языке С и форматирование текста программы на языке С. Требования к программному обеспечению и интерфейсу. Конфигурация технических средств и оценка надежности.
курсовая работа [1,6 M], добавлен 22.06.2011Понятие и ключевое отличие распределенной разработки программного обеспечения, его достоинства и недостатки. Концептуальное решение и выбор типа разработки. Особенности программного обеспечения с открытым исходным кодом. Идея и развитие Open Source.
курсовая работа [97,7 K], добавлен 14.12.2012Изучение стадий и этапов разработки программного обеспечения и эксплуатационных документов. Обзор создания архитектуры, распространения и поддержки системы приложения. Анализ проблем интерфейсов между программным обеспечением и операционной системой.
курсовая работа [1,2 M], добавлен 30.04.2012