Алексей Молчанов - Системное программное обеспечение. Лабораторный практикум
- Название:Системное программное обеспечение. Лабораторный практикум
- Автор:
- Жанр:
- Издательство:Array Издательство «Питер»
- Год:2005
- Город:Санкт-Петербург
- ISBN:978-5-469-00391-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алексей Молчанов - Системное программное обеспечение. Лабораторный практикум краткое содержание
Книга ориентирована на студентов, обучающихся в технических вузах по специальностям, связанным с вычислительной техникой. Но она будет также полезна всем, чья деятельность так или иначе касается разработки программного обеспечения.
Системное программное обеспечение. Лабораторный практикум - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
begin
TakePrevAsm; {Берем предыдущую команду и значение из eax}
{ Запоминаем имена первого и второго операндов }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ Если имя первого операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
сравниваем eax со вторым операндом }
if sReg1 = then
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]))
else { Если имя второго операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
сравниваем eax с первым операндом в обратном порядке }
if sReg2 = then
listCode.Add(Format(#9'cmp'#9 %s,eax'#9 { %s },
[sReg1,listTriad[i].MakeString(i)]))
else { Если оба операнда не пустые, то надо:
– сначала загрузить в eax первый операнд;
– сравнить eax со вторым операндом. }
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]));
end; { Загружаем в младший бит eax 1 или 0
в зависимости от флага сравнения }
listCode.Add(Format(#9'set%s'#9'al',[sOp]));
listCode.Add(#9'and'#9'eax,1); {очищаем остальные биты}
if listTriad[i].Info <> 0 then { Если триада связана с
begin { регистром, запоминаем результат в этом регистре }
sReg1:= GetRegName(listTriad[i].Info);
{ При этом запоминаем, что сейчас находится в eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg1]),
TObject(PChar(sReg1)));
end;
end;
begin { Тело главной функции }
iCnt:= listTriad.Count-1; { Количество триад в списке }
for i:=0 to iCnt do
begin { Цикл по всем триадам от начала списка }
{ Если триада помечена, создаем локальную метку
в списке команд ассемблера }
if listTriad[i].IsLinked then
listCode.Add(Format(@M%d:,[i+1]));
{ Генерация кода в зависимости от типа триады }
case listTriad[i].TrdType of
{ Код для триады IF }
TRD_IF: { Если операнд – константа, }
begin {(это возможно в результате оптимизации)}
if listTriad[i][1].OpType = OP_CONST then
begin { Условный переход превращается
в безусловный, если константа = 0,}
if listTriad[i][1].ConstVal = 0 then
listCode.Add(Format(#9'jmp'#9 @M%d'#9 { %s },
[listTriad[i][2].TriadNum+1,
listTriad[i].MakeString(i)]));
end { а иначе вообще генерировать код не нужно.}
else { Если операнд – не константа }
begin { Берем имя первого операнда }
sR:= GetOpName(i,listTriad,1);
{ Если имя первого операнда пустое,
значит он уже есть в регистре eax
от выполнения предыдущей триады, }
if sR = then
{ тогда надо выставить флаг «Z», сравнив eax
с ним самим, но учитывая, что предыдущая
триада для IF – это либо сравнение, либо
логическая операция, это можно опустить}
else { иначе надо сравнить eax с операндом }
listCode.Add(Format(#9'cmp'#9 %s,0,[sR]));
{Переход по условию «NOT Z» на ближайшую метку}
listCode.Add(Format(#9'jnz'#9 @F%d'#9 { %s },
[i,listTriad[i].MakeString(i)]));
{ Переход по прямому условию на дальнюю метку }
listCode.Add(Format(#9'jmp'#9 @M%d',
[listTriad[i][2].TriadNum+1]));
{ Метка для ближнего перехода }
listCode.Add(Format(@F%d:,[i]));
end;
end;
{ Код для бинарных логических операций }
TRD_OR: MakeOper2('or', );
TRD_XOR: MakeOper2('xor', );
TRD_AND: MakeOper2('and', );
{ Код для операции NOT (так как NOT(0)=FFFFFFFF,
то нужна еще операция: AND eax,1 }
TRD_NOT: MakeOper1('not','and',1);
{ Код для операций сравнения по их флагам }
TRD_LT: MakeCompare('l');
TRD_GT: MakeCompare('g');
TRD_EQ: MakeCompare('e');
TRD_NEQ: MakeCompare('ne');
{ Код для бинарных арифметических операций }
TRD_ADD: MakeOper2('add', );
TRD_SUB: MakeOper2('sub','neg');
{ Код для унарного минуса }
TRD_UMIN: MakeOper1('neg', ,2);
TRD_ASSIGN: { Код для операции присвоения }
begin {Берем предыдущую команду и значение из eax}
TakePrevAsm;
sR:= GetOpName(i,listTriad,2); {Имя второго операнда}
{ Если имя второго операнда пустое, значит он уже есть
в регистре eax от выполнения предыдущей триады}
if sR <> then
begin {иначе генерируем код загрузки второго операнда}
sVal:= MakeMove(sR,sPrev,sVal,flagOpt);
if sVal <> then listCode.Add(sVal);
end; { Из eax записываем результат в переменную
с именем первого операнда }
sVal:= listTriad[i][1].VarLink.VarName;
if sVal = NAME_FUNCT then sVal:= NAME_RESULT;
sVal:= Format(#9'mov'#9 %s,eax'#9 { %s },
[sVal,listTriad[i].MakeString(i)]);
{ При этом запоминаем, что было в eax }
listCode.AddObject(sVal,TObject(PChar(sR)));
end;
{ Код для операции безусловного перехода }
TRD_JMP: listCode.Add(
Format(#9'jmp'#9 @M%d'#9 { %s },
[listTriad[i][2].TriadNum+1,
listTriad[i].MakeString(i)]));
{ Код для операции NOP }
TRD_NOP: listCode.Add(Format(#9'nop'#9#9 { %s },
[listTriad[i].MakeString(i)]));
end{case};
end{for};
Result:= listCode.Count;
end;
end.
Модуль интерфейса с пользователем
unit FormLab4;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ComCtrls, Grids, ExtCtrls,
LexElem, SyntSymb, Triads;
type { Типы возможных ошибок компилятора: файловая,
лексическая, синтаксическая, семантическая или ошибок нет}
TErrType = (ERR_FILE,ERR_LEX,ERR_SYNT,ERR_TRIAD,ERR_NO);
TCursovForm = class(TForm) { главная форма программы }
PageControl1: TPageControl;
SheetFile: TTabSheet;
SheetLexems: TTabSheet;
BtnExit: TButton;
GroupText: TGroupBox;
ListIdents: TMemo;
EditFile: TEdit;
BtnFile: TButton;
BtnLoad: TButton;
FileOpenDlg: TOpenDialog;
GridLex: TStringGrid;
SheetSynt: TTabSheet;
TreeSynt: TTreeView;
SheetTriad: TTabSheet;
GroupTriadAll: TGroupBox;
Splitter1: TSplitter;
GroupTriadSame: TGroupBox;
Splitter2: TSplitter;
GroupTriadConst: TGroupBox;
ListTriadAll: TMemo;
ListTriadConst: TMemo;
ListTriadSame: TMemo;
CheckDel_C: TCheckBox;
CheckDelSame: TCheckBox;
SheetAsm: TTabSheet;
ListAsm: TMemo;
CheckAsm: TCheckBox;
procedure BtnLoadClick(Sender: TObject);
procedure BtnFileClick(Sender: TObject);
procedure EditFileChange(Sender: TObject);
procedure BtnExitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
listLex: TLexList; { Список лексем }
symbStack: TSymbStack; { Синтаксический стек }
listTriad: TTriadList; { Список триад }
{ Имена файлов: входного, результата и ошибок }
sInpFile,sOutFile,sErrFile: string;
{ Функция записи стартовых данных в файл ошибок }
procedure StartInfo(const sErrF: string);
{ Функция обработки командной строки }
procedure ProcessParams(
var flOptC,flOptSame,flOptAsm: Boolean);
{ Инициализация таблицы отображения списка лексем }
procedure InitLexGrid;
{ Процедура отображения синтаксического дерева }
procedure MakeTree(nodeTree: TTreeNode;
symbSynt: TSymbol);
{ Процедура информации об ошибке }
procedure ErrInfo(const sErrF,sErr: string;
iPos,iLen: integer);
{ Функция запуска компилятора }
function CompRun(const sInF,sOutF,sErrF: string;
var symbRes: TSymbol; flTrd,flDelC,flDelSame,flOptC,
flOptSame,flOptAsm: Boolean): TErrType;
end;
var CursovForm: TCursovForm;
implementation
{$R *.DFM}
uses FncTree,LexType,LexAuto,TrdType,TrdMake,TrdAsm,TrdOpt;
procedure TCursovForm.InitLexGrid;
Читать дальшеИнтервал:
Закладка: