end;
function MakeAsmCode(
listTriad: TTriadList;{входной список триад}
listCode: TStrings;{список строк результирующего кода}
flagOpt: Boolean{флаг оптимизации}): integer;
{ Функция построения ассемблерного кода по списку триад }
var i,iCnt: integer;{счетчик и переменная цикла}
sR: string;{строка для имени регистра}
sPrev,sVal: string;
{строки для хранения предыдущей команды и значения eax}
procedure TakePrevAsm;
{ Процедура, выделяющая предыдущую команду и значение eax
из списка результирующих команд }
var j: integer;
begin
j:= listCode.Count;
if j > 0 then
begin
sPrev:= listCode[j-1];
sVal:= StrPas(PChar(listCode.Objects[j-1]));
end
else
begin
sPrev:= ; sVal:= ;
end;
end;
procedure MakeOper1(const sOp,{код операции}
sAddOp: string;{код дополнительной операции}
iOp: integer{номер операнда в триаде});
{ Функция генерации кода для унарных операций }
var sReg{строка для имени регистра}: string;
begin
TakePrevAsm; {Берем предыдущую команду и значение из eax}
{ Запоминаем имя операнда }
sReg:= GetOpName(i,listTriad,iOp);
if sReg <> then { Если имя пустое, операнд уже есть в
регистре eax от выполнения предыдущей триады,}
begin { иначе его нужно занести в eax }
{ Вызываем функцию генерации кода занесения операнда }
sReg:= MakeMove(sReg,sPrev,sVal,flagOpt);
if sReg <> then listCode.Add(sReg);
end; { Генерируем непосредственно код операции }
listCode.Add(Format(#9 %s'#9'eax'#9 { %s },
[sOp,listTriad[i].MakeString(i)]));
if sAddOp <> then { Если есть дополнительная операция,
генерируем ее код }
listCode.Add(Format(#9 %s'#9'eax,1,[sAddOp]));
if listTriad[i].Info <> 0 then { Если триада связана с
begin { регистром, запоминаем результат в этом регистре }
sReg:= GetRegName(listTriad[i].Info);
{ При этом запоминаем, что сейчас находится в eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg]),
TObject(PChar(sReg)));
end;
end;
procedure MakeOper2(const sOp,{код операции}
sAddOp: string{код дополнительная операции});
{ Функция генерации кода для бинарных арифметических
и логических операций }
var sReg1,sReg2{строки для имен регистров}: string;
begin
TakePrevAsm; {Берем предыдущую команду и значение из eax}
{ Запоминаем имена первого и второго операндов }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ Если имя первого операнда пустое, значит, он уже
есть в регистре eax от выполнения предыдущей триады -
вызываем функцию генерации кода для второго операнда }
if (sReg1 = ) or (sReg1 = sVal) then
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt))
else { Если имя второго операнда пустое, значит он уже
есть в регистре eax от выполнения предыдущей триады -
вызываем функцию генерации кода для первого операнда }
if (sReg2 = ) or (sReg2 = sVal) then
begin
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg1,
sPrev,sVal,flagOpt));
{ Если есть дополнительная операция, генерируем ее код
(когда операция несимметричная – например "-") }
if sAddOp <> then
listCode.Add(Format(#9 %s'#9'eax',[sAddOp]));
end
else { Если оба операнда не пустые, то надо:
– сначала загрузить в eax первый операнд;
– сгенерировать код для обработки второго операнда.}
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt));
end;
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;
procedure MakeCompare(const sOp: string
{флаг операции сравнения});
{ Функция генерации кода для операций сравнения }
var sReg1,sReg2{строки для имен регистров}: string;
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 первый операнд;
Читать дальше
Конец ознакомительного отрывка
Купить книгу