Алексей Молчанов - Системное программное обеспечение. Лабораторный практикум
- Название:Системное программное обеспечение. Лабораторный практикум
- Автор:
- Жанр:
- Издательство:Array Издательство «Питер»
- Год:2005
- Город:Санкт-Петербург
- ISBN:978-5-469-00391-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алексей Молчанов - Системное программное обеспечение. Лабораторный практикум краткое содержание
Книга ориентирована на студентов, обучающихся в технических вузах по специальностям, связанным с вычислительной техникой. Но она будет также полезна всем, чья деятельность так или иначе касается разработки программного обеспечения.
Системное программное обеспечение. Лабораторный практикум - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
listTriad.Add(TTriad.Create(TRD_UMIN,Opers));
end;
{ Для логических, арифметических или операторных скобок
рекурсивно вызываем функцию для второго символа }
1,7,19,26:{'progEend.,'beginEend', (E), (B) }
Result:= MakeTriadListNOP(symbTop[1],listTriad);
3:{E;E Для списка операторов нужно рекурсивно вызвать}
begin { функцию два раза }
Result:= MakeTriadListNOP(symbTop[0],listTriad);
if Result <> nil then Exit;
Result:= MakeTriadListNOP(symbTop[2],listTriad);
end;
27,28: Result:= nil; { Для лексем ничего не нужно }
{ Во всех остальных случаях нужно рекурсивно вызвать
функцию для первого символа }
else Result:= MakeTriadListNOP(symbTop[0],listTriad);
end{case Rule};
end;
function MakeTriadList(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{ Функция создания списка триад начиная от корневого
символа дерева синтаксического разбора }
var
i: integer;
Opers: TOpArray;
Trd: TTriad;
begin { Создаем список триад }
Result:= MakeTriadListNOP(symbTop,listTriad);
if Result = nil then {Если ошибка, прерываем выполнение}
with listTriad do
begin { Создаем пустую триаду «NOP» в конце списка }
Opers[1].OpType:= OP_CONST;
Opers[1].ConstVal:= 0;
Opers[2].OpType:= OP_CONST;
Opers[2].ConstVal:= 0;
Add(TTriad.Create(TRD_NOP,Opers));
for i:=Count-1 downto 0 do
begin {Для всех триад в списке расставляем флаг ссылки}
Trd:= Triads[i];
if Trd.TrdType in [TRD_IF,TRD_JMP] then
begin { Если триада «переход» («IF» или «JMP»)
ссылается на другую триаду,}
if Trd.OpTypes[2] = OP_LINK then
listTriad[Trd.Links[2]].IsLinked:= True;
{ то ту триаду надо пометить }
end;
end;
end;
end;
end.
Модуль построения ассемблерного кода по списку триад
unit TrdAsm;
{!!! Зависит от целевой вычислительной системы!!! }
interface
{ Модуль распределения регистров и построения ассемблерного
кода по списку триад }
uses Classes, TrdType, Triads;
const { Префикс наименования временных переменных }
TEMP_VARNAME = _Tmp';
NUM_PROCREG = 6; { Количество доступных регистров }
{ Функция распределения регистров и временных переменных
для хранения промежуточных результатов триад }
function MakeRegisters(listTriad: TTriadList): integer;
{ Функция построения ассемблерного кода по списку триад }
function MakeAsmCode(listTriad: TTriadList;
listCode: TStrings;
flagOpt: Boolean): integer;
implementation
uses SysUtils;
function MakeRegisters(listTriad: TTriadList): integer;
{ Функция распределения регистров и временных переменных
для хранения промежуточных результатов триад.
Результат: количество необходимых временных переменных }
var
i,j,iR,iCnt,iNum: integer;{Счетчики и переменные циклов}
{ Динамический массив для запоминания занятых регистров }
listReg: TList;
begin { Создаем массив для хранения занятых регистров }
listReg:= TList.Create;
Result:= 0;
if listReg <> nil then
try { Обнуляем информационное поле у всех триад }
for i:=listTriad.Count-1 downto 0 do
listTriad[i].Info:= 0;
{ Цикл по всем триадам. Обязательно с конца списка! }
for i:=listTriad.Count-1 downto 0 do
for j:=1 to 2 do { Цикл по всем (2) операндам }
{ Если триада – линейная операция, или «IF»
(первый операнд), или присвоение (второй операнд) }
if ((listTriad[i].TrdType in TriadLineSet)
or (listTriad[i].TrdType = TRD_IF) and (j = 1)
or (listTriad[i].TrdType = TRD_ASSIGN) and (j = 2))
{ и операндом является ссылка на другую триаду }
and (listTriad[i][j].OpType = OP_LINK) then
begin { Запоминаем номер триады, на которую направлена ссылка }
iNum:= listTriad[i][j].TriadNum;
{ Если триаде еще не назначен регистр и если это
не предыдущая триада – надо ей назначить регистр }
if (listTriad[iNum].Info = 0) and (iNum <> i-1) then
begin { Количество назначенных регистров }
iCnt:= listReg.Count-1;
for iR:=0 to iCnt do
begin{ Цикл по массиву назначенных регистров }
{ Если область действия регистра за пределами
текущей триады, то его можно использовать }
if longint(listReg[iR]) >= i then
begin { Запоминаем область действия регистра }
listReg[iR]:= TObject(iNum);
{ Назначаем регистр триаде с номером iNum }
listTriad[iNum].Info:= iR+1;
Break; { Прерываем цикл по массиву регистров }
end;
end; { Если ни один из использованных регистров
не был назначен, надо брать новый регистр }
if listTriad[iNum].Info = 0 then
begin { Добавляем запись в массив регистров,
указываем ей область действия iNum }
listReg.Add(TObject(iNum));
{ Назначаем новый регистр триаде с номером iNum }
listTriad[iNum].Info:= listReg.Count;
end;
end;
end;{ Результат функции: количество записей в массиве
регистров -1, за вычетом числа доступных регистров}
Result:= listReg.Count – (NUM_PROCREG-1);
finally listReg.Free;
end;
end;
function GetRegName(iInfo: integer): string;
{ Функция наименования регистров процессора }
begin
case iInfo of
0: Result:= 'eax';
1: Result:= 'ebx';
2: Result:= 'ecx';
3: Result:= 'edx';
4: Result:= 'esi';
5: Result:= 'edi';
{ Если это не один из регистров – значит,
даем имя временной переменной }
else Result:=
Format(%s%d',[TEMP_VARNAME,iInfo-NUM_PROCREG]);
end{case};
end;
function GetOpName(i: integer; listTriad: TTriadList;
iOp: integer): string;
{ Функция наименования операнда триады
i – номер триады в списке;
listTriad – список триад;
iOp – номер операнда триады }
var iNum: integer; {номенр триады по ссылке}
Triad: TTriad; {текущая триада}
begin
Triad:= listTriad[i]; { Запоминаем текущую триаду }
{ Выборка наименования операнда в зависимости от типа }
case Triad[iOp].OpType of
{ Если константа – значение константы }
OP_CONST: Result:= IntToStr(Triad[iOp].ConstVal);
{ Если переменная – ее имя из таблицы идентификаторов }
OP_VAR:
begin
Result:= Triad[iOp].VarLink.VarName;
{ Если имя совпадает с именем функции,
заменяем его на Result функции }
if Result = NAME_FUNCT then Result:= NAME_RESULT;
end; { Иначе – это регистр }
else { для временного хранения результатов триады }
begin { Запоминаем номер триады }
iNum:= Triad[iOp].TriadNum;
{ Если это предыдущая триада, то операнд не нужен }
if iNum = i-1 then Result:=
else
begin {Берем номер регистра, связанного с триадой}
iNum:= listTriad[iNum].Info;
{ Если регистра нет, то операнд не нужен }
if iNum = 0 then Result:=
{ Иначе имя операнда – это имя регистра }
else Result:= GetRegName(iNum);
end;
end;
end{case};
end;
function MakeMove(const sReg,{имя регистра}
sPrev,{предыдущая команда}
sVal{предыдущая величина в eax}: string;
flagOpt: Boolean{флаг оптимизации}): string;
{ Функция, генерящая код занесения значения в регистр eax }
begin { Если операнд был только что выгружен из eax
или необходимое значение уже есть в аккумуляторе,
нет необходимости записывать его туда снова }
if (Pos(Format(#9'mov'#9 %s,eax',[sReg]), sPrev) = 1)
or (sVal = sReg) then
Читать дальшеИнтервал:
Закладка: