- •Постановка задачи.
- •Теоретический раздел. Основные понятия.
- •Некоторые возможности Макроязыка
- •Структуры данных Макропроцессора
- •Основные алгоритмы программы.
- •Руководство пользователя.
- •Описание макроязыка.
- •Описание разработанных модулей.
- •Список использованной литературы.
- •Листинг программы. Модуль mp.
- •Описание разработанных тестов.
- •Модуль Assembler.
- •Модуль Main.
- •Модуль MacroGen.
- •Модуль Expr.
- •Модуль Strings.
Описание разработанных тестов.
1. В первом тесте проверяется правильность работы макропроцессора с командами AIF и AGO.
Рис. 1.
На рис.1 изображен результат выполнения макропроцессором и ассемблером 1-го и 2-го проходов. Как видно на рисунке, в исходном файле есть только одно внешнее макроопределение – макрос $M1.Этот макрос заносится в ТИМ и ТМО на первом проходе. На втором проходе производится макровызов “$M1”. При обработке макровызова производятся следующие действия. Сначала выводится команда NOP. Затем проверяется условие &A ==10. Пока оно ложно выводится команда MOV R1 &A, где вместо &A подставляется текущее значение этой переменной. В конце завершается обработка макровызова и выводится директива END.
2. Во втором тесте программы проверяется обработка макровызовов с различными значениями параметров.
Рис. 2.
На рис. 2 изображен результат выполнения программы. В исходном файле имеется одно макроопределение $M1, который заносится в ТИМ и ТМО на первом проходе. На втором проходе производится 3 макровызова макроса M1 “$M1”, “$M1 &A = 10”, “$M1 &A = 100”. При обработке макровызова выполняются следующие действия. Выводится строка MOV R1 &A. Затем производится подстановка значения параметра &A в строку MOV &A. Для каждого макровызова подставляется соответствующее значение переменной &A. В случае 1-го макровызова значение данной переменной не задано во время вызова, поэтому ей будет присвоено значении по умолчанию, равное 0. В 2-м и 3-м макровызовах переменная &A принимает значения 10 и 100 соответственно. Далее завершается обработка макровызова и выводится директива END.
Список использованной литературы.
1. Бек Л. Введение в системное программирование. М. Мир. 1988г. 448 с.
2. Браун П. Макропроцессоры и мобильность программного обеспечения. М. Мир 1977г. 254с.
3. Кэмпбел-Келли М.Введение в макросы. Пер. с англ.1978. 152 с
4. Фельдман С.К. Системное программирование на персональном компьютере. – 2е изд. – М.: Букпресс, 2006.— 512 с
Листинг программы. Модуль mp.
uses
Forms,
SysUtils,
Windows,
AVLTree,
Main in 'Main.pas' {Form1},
Expr in 'Expr.pas',
Strings in 'Strings.pas',
MacroGen in 'MacroGen.pas',
Assembler in 'Assembler.pas';
{$R *.res}
{$APPTYPE CONSOLE}
const
PAR1 = '/if';
PAR2 = '/mof';
PAR3 = '/aof';
PAR4 = '/?';
ERRORS_FILE_NAME = 'errors.txt';
procedure showHelp();
begin
writeln;
writeln('Project1 [' + PAR1 + ' <filename>] [' + PAR2 + ' <filename>] [' + PAR3 + ' <filename>] [' + PAR4 + ']');
writeln(#9 + PAR1 + ' - input filename (default = ' + inputFileName + ')');
writeln(#9 + PAR2 + ' - macroassembler output file name (default = ' + macroOutputFileName + ')');
writeln(#9 + PAR3 + ' - assembler output file name (default = ' + asmOutputFileName + ')');
writeln(#9 + PAR4 + ' - help');
writeln;
end;
function getParamIndex(param: string): integer;
begin
result:=0;
param := ansiLowerCase(param);
if (param = PAR1) then
result := 1;
if (param = PAR2) then
result := 2;
if (param = PAR3) then
result := 3;
if (param = PAR4) then
result := 4;
end;
function isRightFileName(fileName: string; rw: boolean): boolean;
var
tmpFile: textFile;
begin
result := true;
if (fileName='') then
begin
result:=false;
exit;
end;
try
assignFile(tmpFile, fileName);
if (rw) then
rewrite(tmpFile)
else
reset(tmpFile);
closefile(tmpFile);
except
result:=false;
end;
end;
procedure outErrors(fileName, errors: string);
var
outputFile: textFile;
begin
assignFile(outputFile, fileName);
rewrite(outputFile);
writeln(outputFile, errors);
closefile(outputFile);
end;
var
result : TResult;
Error : TError;
currParamStr,
currLexem,
Header : string;
i,
charPos,
numCurrOutputStr,
currParamIndex : integer;
isParamFound : array [1..4] of boolean;
currOutput : array [0..MAX_OUTPUT_LEN - 1] of string;
begin
SymbNameTree := TAVLTree.Create;
if (paramStr(1) = '') then
begin
freeConsole;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end else
begin
for i := 1 to 4 do
begin
isParamFound[i] := false;
end;
i:=1;
while (paramStr(i) <> '') do
begin
currParamStr := paramStr(i);
currParamIndex := getParamIndex(currParamStr);
if (currParamIndex = 0) then
begin
writeln('Error: bad parameter: ' + currParamStr);
if (not isParamFound[4]) then
showHelp;
exit;
end;
if (isParamFound[currParamIndex]) then
begin
writeln('Error: duplicating params');
exit;
end;
isParamFound[currParamIndex] := true;
case (currParamIndex) of
1: begin inputFileName := paramStr(i + 1); inc(i, 2); end;
2: begin macroOutputFileName := paramStr(i + 1); inc(i, 2); end;
3: begin asmOutputFileName := paramStr(i + 1); inc(i, 2); end;
4: begin showHelp; inc(i); end;
end;
end;
if (not isRightFileName(inputFileName, false)) then
begin
writeln('Error: incorrect input file name or file is not found: ' + inputFileName);
exit;
end;
if (not isRightFileName(macroOutputFileName, true)) then
begin
writeln('Error: incorrect output file name or file is not found: ' + macroOutputFileName);
exit;
end;
if (not isRightFileName(asmOutputFileName, true)) then
begin
writeln('Error: incorrect output file name or file is not found: ' + asmOutputFileName);
exit;
end;
if (isParamFound[1] or isParamFound[2] or isParamFound[3]) then
begin
numSrcStr := loadSrcCode(inputFileName);
result := doFirstStep(srcCode, numSrcStr);
if (result.code <> NORM_RESULT) then
begin
writeln('Errors was found!');
outErrors(ERRORS_FILE_NAME, ERR_DESC[result.code - 1] + ' : ' + result.additionalInfo);
exit;
end;
result := doSecondStep(srcCode, numSrcStr);
if (result.code <> NORM_RESULT) then
begin
writeln('Errors was found!');
outErrors(ERRORS_FILE_NAME, ERR_DESC[result.code - 1] + ' : ' + result.additionalInfo);
exit;
end;
getCurrOutput(currOutput, numCurrOutputStr);
numLines := numCurrOutputStr;
for i := 0 to numCurrOutputStr - 1 do
begin
charPos := 1;
currLexem := getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR);
if ((currLexem <> '') and (currLexem[1] = ASM_MARK_SYMBOL)) then
begin
InputTable[i].SymbName := currLexem;
InputTable[i].MOpCode := ansiUpperCase(getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR));
end else
InputTable[i].MOpCode := ansiUpperCase(currLexem);
InputTable[i].Opd1 := getNextLexem(currOutput[i], charPos, COMMON_SEPARATOR);
InputTable[i].Opd2 := trim(getNextLexem(currOutput[i], charPos, ''));
end;
SymbNameTree.RemoveAll;
FirstParse(InputTable, TempTable, SymbNameTree, NumSymbNames, Error, NumLines, ProgLen, Header);
Output[0] := Header;
if (Error.ErrType <> eNoErr) then
begin
writeln('Errors was found!');
outErrors(ERRORS_FILE_NAME, 'Строка ' + IntToStr(Error.StrNum + 1) + ': ' + ErrText[Error.ErrType]);
exit;
end;
SecondParse(TempTable, Output, Error, SymbNameTree, NumSymbNames, NumLines);
if (Error.ErrType <> eNoErr) then
begin
writeln('Errors was found!');
outErrors(ERRORS_FILE_NAME, 'Строка ' + IntToStr(Error.StrNum + 1) + ': ' + ErrText[Error.ErrType]);
exit;
end;
outResultInFiles;
writeln;
writeln('Done');
end;
end;
end.
