📄 dcinstrsource.pas
字号:
Result := TDuoSource.Create(Source1.Replace(FindSource, ReplaceSource),
Source2.Replace(FindSource, ReplaceSource), SourceType);
end;
function TDuoSource.Compare(ASource: IInstrSource): Boolean;
var
ADuoSource: IDuoSource;
begin
Result := Succeeded(ASource.QueryInterface(IDuoSource, ADuoSource)) and
(ADuoSource.SourceType = SourceType) and Source1.Compare(ADuoSource.Source1) and
Source2.Compare(ADuoSource.Source2);
end;
function TDuoSource.GetSource1: IInstrSource;
begin
Result := FSource1;
end;
function TDuoSource.GetSource2: IInstrSource;
begin
Result := FSource2;
end;
function TDuoSource.GetSourceType: TDuoSourceType;
begin
Result := FSourceType;
end;
procedure TDuoSource.GetSources(Callback: TGetSourcesCallback);
begin
inherited GetSources(Callback);
Source1.GetSources(Callback);
Source2.GetSources(Callback);
end;
function TDuoSource.AsPascal(Callback: TAsPascalCallback): string;
const
SourceTypeNames: array[TDuoSourceType] of string =
('*', 'div', '+', '-');
begin
Result := Format('(%s %s %s)', [Source1.AsPascal(Callback), SourceTypeNames[SourceType],
Source2.AsPascal(Callback)]);
Callback(Self, Result);
end;
function TDuoSource.Optimize: IInstrSource;
var
ADuoSource: IDuoSource;
AConstSource1: IConstSource;
AConstSource2: IConstSource;
begin
Result := nil;
if Succeeded(Source1.QueryInterface(IConstSource, AConstSource1)) and
Succeeded(Source2.QueryInterface(IConstSource, AConstSource2)) then
begin
// Calculate operations on constant values.
case SourceType of
dstAdd: Result := CreateConstSource(AConstSource1.Value + AConstSource2.Value);
dstSub: Result := CreateConstSource(AConstSource1.Value - AConstSource2.Value);
dstMultiply: Result := CreateConstSource(AConstSource1.Value * AConstSource2.Value);
dstDivide: Result := CreateConstSource(AConstSource1.Value div AConstSource2.Value);
end;
end
// Apply some add / sub on constant values.
else if (SourceType in [dstAdd, dstSub]) and
Succeeded(Source2.QueryInterface(IConstSource, AConstSource1)) and
Succeeded(Source1.QueryInterface(IDuoSource, ADuoSource)) and
(ADuoSource.SourceType in [dstAdd, dstSub]) and
Succeeded(ADuoSource.Source2.QueryInterface(IConstSource, AConstSource2)) then
begin
if SourceType = ADuoSource.SourceType then
Result := CreateDuoSource(ADuoSource.Source1.Optimize,
CreateConstSource(AConstSource1.Value + AConstSource2.Value), SourceType)
else
Result := CreateDuoSource(ADuoSource.Source1.Optimize,
CreateConstSource(AConstSource1.Value - AConstSource2.Value), SourceType)
end
// Add / Sub 0 doesn't do anything.
else if (SourceType in [dstAdd, dstSub]) and
Succeeded(Source1.QueryInterface(IConstSource, AConstSource1)) and
(AConstSource1.Value = 0) then
begin
Result := Source2.Optimize;
end
else if (SourceType in [dstAdd, dstSub]) and
Succeeded(Source2.QueryInterface(IConstSource, AConstSource1)) and
(AConstSource1.Value = 0) then
begin
Result := Source1.Optimize;
end;
// If there isn't a source yet, create one based on the optimized sources.
if Result = nil then
Result := CreateDuoSource(Source1.Optimize, Source2.Optimize, SourceType);
end;
(*
{ TMultiSource }
constructor TMultiSource.Create(const AItems: array of IInstrSource; ASourceType: TMultiSourceType);
var
I: Integer;
begin
FCount := Length(AItems);
GetMem(FItems, FCount * SizeOf(TInstrSource));
for I := 0 to FCount -1 do
FItems^[I] := AItems[I + Low(AItems)];
end;
destructor TMultiSource.Destroy;
var
I: Integer;
begin
for I := 0 to FCount -1 do
FItems^[I] := nil;
FreeMem(FItems, FCount * SizeOf(TInstrSource));
inherited Destroy;
end;
function TMultiSource.Replace(FindSource, ReplaceSource: IInstrSource): IInstrSource;
var
I: Integer;
AItems: array of IInstrSource;
begin
if Compare(FindSource) then
Result := ReplaceSource
else
begin
SetLength(AItems, Count);
for I := 0 to Count -1 do
AItems[I] := Items[I].Replace(FindSource, ReplaceSource);
Result := TMultiSource.Create(AItems, SourceType);
end;
end;
function TMultiSource.Compare(ASource: IInstrSource): Boolean;
var
AMultiSource: IMultiSource;
I: Integer;
begin
Result := Succeeded(ASource.QueryInterface(IMultiSource, AMultiSource)) and
(AMultiSource.SourceType = SourceType);
for I := 0 to Count -1 do
begin
if not Result then Exit;
Result := Items[I].Compare(AMultiSource.Items[I]);
end;
end;
function TMultiSource.GetItem(Index: Integer): IInstrSource;
begin
Result := FItems^[Index];
end;
function TMultiSource.GetCount: Integer;
begin
Result := FCount;
end;
function TMultiSource.GetSourceType: TMultiSourceType;
begin
Result := FSourceType;
end;
*)
{ TRegSource }
constructor TRegSource.Create(AReg: TRegister; ARegType: TRegisterType);
begin
inherited Create;
FReg := AReg;
FRegType := ARegType;
end;
function TRegSource.Replace(FindSource, ReplaceSource: IInstrSource): IInstrSource;
begin
if Compare(FindSource) then
Result := ReplaceSource
else
Result := Self;
end;
function TRegSource.Compare(ASource: IInstrSource): Boolean;
var
ARegSource: IRegSource;
begin
Result := Succeeded(ASource.QueryInterface(IRegSource, ARegSource)) and
(ARegSource.Reg = Reg) and (ARegSource.RegType = RegType);
end;
function TRegSource.GetReg: TRegister;
begin
Result := FReg;
end;
function TRegSource.GetRegType: TRegisterType;
begin
Result := FRegType;
end;
function TRegSource.AsPascal(Callback: TAsPascalCallback): string;
const
RegNames: array[TRegister, TRegisterType] of string =
(('ah', 'al', 'ax', 'eax'), ('ch', 'cl', 'cx', 'ecx'), ('dh', 'dl', 'dx', 'edx'),
('bh', 'bl', 'bx', 'ebx'), ('', '', 'sp', 'esp'), ('', '', '', 'ebp'),
('', '', 'si', 'esi'), ('', '', '', ''));
begin
Result := RegNames[Reg, RegType];
Callback(Self, Result);
end;
{ TConstSource }
constructor TConstSource.Create(AValue: Cardinal);
begin
inherited Create;
FValue := AValue;
end;
function TConstSource.Replace(FindSource, ReplaceSource: IInstrSource): IInstrSource;
begin
if Compare(FindSource) then
Result := ReplaceSource
else
Result := Self;
end;
function TConstSource.Compare(ASource: IInstrSource): Boolean;
var
AConstSource: IConstSource;
begin
Result := Succeeded(ASource.QueryInterface(IConstSource, AConstSource)) and
(AConstSource.Value = Value);
end;
function TConstSource.GetValue: Cardinal;
begin
Result := FValue;
end;
function TConstSource.AsPascal(Callback: TAsPascalCallback): string;
begin
Result := IntToStr(Value);
Callback(Self, Result);
end;
{ TAddressSource }
constructor TAddressSource.Create(AAddress: TAddress);
begin
inherited Create;
FAddress := AAddress;
end;
function TAddressSource.Replace(FindSource, ReplaceSource: IInstrSource): IInstrSource;
begin
if Compare(FindSource) then
Result := ReplaceSource
else
Result := Self;
end;
function TAddressSource.Compare(ASource: IInstrSource): Boolean;
var
AAddressSource: IAddressSource;
begin
Result := Succeeded(ASource.QueryInterface(IAddressSource, AAddressSource)) and
(AAddressSource.Address = Address);
end;
function TAddressSource.GetAddress: TAddress;
begin
Result := FAddress;
end;
function TAddressSource.AsPascal(Callback: TAsPascalCallback): string;
begin
Result := '$' + IntToHex(Integer(Address), 8);
Callback(Self, Result);
end;
// Interface creation functions implementations.
(*
function CreateMonoSource(ASource: IInstrSource; ASourceType: TMonoSourceType): IMonoSource;
begin
Result := TMonoSource.Create(ASource, ASourceType);
end;
*)
function CreateDuoSource(ASource1, ASource2: IInstrSource; ASourceType: TDuoSourceType): IDuoSource;
begin
Result := TDuoSource.Create(ASource1, ASource2, ASourceType);
end;
(*
function CreateMultiSource(const AItems: array of IInstrSource; ASourceType: TMultiSourceType): IMultiSource;
begin
Result := TMultiSource.Create(AItems, ASourceType);
end;
*)
function CreateRegSource(AReg: TRegister; ARegType: TRegisterType): IRegSource;
begin
Result := TRegSource.Create(AReg, ARegType);
end;
function CreateConstSource(AValue: Cardinal): IConstSource;
begin
Result := TConstSource.Create(AValue);
end;
function CreateAddressSource(AAddress: TAddress): IAddressSource;
begin
Result := TAddressSource.Create(AAddress);
end;
function CreateRefSource(ASource: IInstrSource; ASize: Integer): IRefSource;
begin
Result := TRefSource.Create(ASource, ASize);
end;
// Creates a IIinstrSource from an TOpcInstr
function ConvArgToIInstr(const Arg: TArgument): IInstrSource;
function RefToSource(const Ref: TdaRef): IInstrSource;
function GetMultiplyRef(Multiply: Integer; Reg: TRegister): IInstrSource;
var
Tmp: IInstrSource;
begin
Result := nil;
if Multiply > 0 then
Result := CreateRegSource(Ref.ARegister1, rtDWord);
if Multiply > 1 then
begin
Tmp := CreateConstSource(Multiply);
Result := CreateDuoSource(Result, Tmp, dstMultiply);
end;
end;
var
Tmp: IInstrSource;
IsAddress: Boolean;
begin
// Create the multiply reg instructions.
Result := GetMultiplyRef(Ref.MultiplyReg1, Ref.ARegister1);
Tmp := GetMultiplyRef(Ref.MultiplyReg2, Ref.ARegister2);
// Combine the two Instructions.
if Result = nil then
Result := Tmp
else
Result := CreateDuoSource(Result, Tmp, dstAdd);
// Create the Imm instruction.
if Ref.Immidiate <> nil then
begin
IsAddress := False;
if Assigned(IsImmAddressCallback) then
IsImmAddressCallback(Ref.Immidiate, IsAddress);
if IsAddress then
Tmp := CreateConstSource(Cardinal(Ref.Immidiate))
else
Tmp := CreateConstSource(Cardinal(Ref.Immidiate));
Result := CreateDuoSource(Result, Tmp, dstAdd);
end;
end;
resourcestring
ENotSupportedArgType = 'Not supported instruction source argument type.';
begin
case Arg.ArgumentType of
atNone: Result := nil;
atRegv: Result := CreateRegSource(Arg.Reg, rtDWord);
atRefv:
begin
Result := CreateRefSource(RefToSource(Arg.Ref), 4);
end;
else
raise EdcInstructionError.Create(ENotSupportedArgType);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -