📄 dcopctoinstr.pas
字号:
unit dcOpcToInstr;
interface
uses
dcInstrSource, DisAsmX, SysUtils;
type
{ IInstrOwner }
TInstruction = class;
IInstrOwner = interface(IUnknown)
procedure AddInstr(Instr: TInstruction);
function GetAddress: TAddress;
function GetSize: Integer;
function GetCount: Integer;
function GetItem(Index: Integer): TInstruction;
function GetItemIndex(Item: TInstruction): Integer;
property Address: TAddress read GetAddress;
property Size: Integer read GetSize;
property Count: Integer read GetCount;
// Items are always sorted on address.
property Items[Index: Integer]: TInstruction read GetItem;
property ItemIndexes[Item: TInstruction]: Integer read GetItemIndex;
end;
EInstructionError = class(Exception);
{ TInstruction }
TInstruction = class(TObject)
private
FAddress: TAddress;
FSize: Integer;
public
constructor Create(AAddress: TAddress); virtual; abstract;
constructor CreateSized(AAddress: TAddress; ASize: Integer);
function AllowReplaceCallBack(const Instrs: array of TInstruction): Boolean;
property Address: TAddress read FAddress;
property Size: Integer read FSize;
end;
TInstructionClass = class of TInstruction;
{ TAsmInstr }
TAsmInstr = class(TInstruction)
private
FInstrText: string;
public
constructor CreateOpc(AAddress: TAddress; ASize: Integer);
constructor Create(AAddress: TAddress); override;
function AllowReplaceCallBack(const Instrs: array of TInstruction): Boolean;
property InstrText: string read FInstrText;
end;
{ TAssignInstr }
TAssignInstr = class(TInstruction)
private
FTarget: IInstrSource;
FSource: IInstrSource;
public
constructor Create(AAddress: TAddress); override;
constructor CreateAssign(AAddress: TAddress; ASize: Integer; ATarget, ASource: IInstrSource);
property Target: IInstrSource read FTarget;
property Source: IInstrSource read FSource;
end;
{ TRetInstr }
TRetInstr = class(TInstruction)
private
FPopSize: Integer;
public
constructor Create(AAddress: TAddress); override;
property PopSize: Integer read FPopSize;
end;
{ TODO -cAdditions : Add other instruction types. }
{ TCallInstr = class(TInstruction)
private
FTarget: IInstrSource;
public
constructor Create(AAddress: TAddress); override;
property Target: IInstrSource read FTarget;
end;
TJumpInstr = class(TInstruction)
private
FTarget: IInstrSource;
public
constructor Create(AAddress: TAddress); override;
property Target: IInstrSource read FTarget;
end;
}
procedure CreateInstr(Address: TAddress; InstrOwner: IInstrOwner);
implementation
uses
dcAssignInstrTable, DisAsm;
{ TInstruction }
constructor TInstruction.CreateSized(AAddress: TAddress; ASize: Integer);
begin
inherited Create;
FAddress := AAddress;
FSize := ASize;
end;
function TInstruction.AllowReplaceCallBack(const Instrs: array of TInstruction): Boolean;
begin
// Allow replace by default.
Result := True;
end;
{ TAsmInstr }
constructor TAsmInstr.CreateOpc(AAddress: TAddress; ASize: Integer);
var
J: Integer;
begin
inherited CreateSized(AAddress, ASize);
// Just creaet DB instructions
for J := ASize -1 downto 1 do
FInstrText := ', $' + IntToHex(Byte(Pointer(Address + J)^), 2) + FInstrText;
FInstrText := 'DB $' + IntToHex(Byte(Pointer(Address)^), 2) + FInstrText;
end;
constructor TAsmInstr.Create(AAddress: TAddress);
var
ASize: Integer;
begin
// Get the Instruction text and size.
with TDisAsm.Create do
try
FInstrText := GetInstruction(AAddress, ASize);
finally
Free;
end;
inherited CreateSized(AAddress, ASize);
end;
function TAsmInstr.AllowReplaceCallBack(const Instrs: array of TInstruction): Boolean;
begin
// Don't append if there is an Asm instr.
Result := False;
end;
{ TAssignInstr }
constructor TAssignInstr.Create(AAddress: TAddress);
var
Instr: TOpcInstr;
ASize: Integer;
resourcestring
SErrorInInstr = 'Error in instruction';
begin
// Get the instruction.
Instr := GetInstruction(AAddress, ASize);
if (not (Instr.Mnemonic in [mMov, mPush, mPop])) or
(Instr.LoRepPrefix <> lrpNone) or
(Instr.SegPrefix <> spNone) or Instr.AddressSizePrefix or
(Instr.Arguments[3].ArgumentType <> atNone) then
raise EInstructionError.Create(SErrorInInstr);
// inherited create using the Size of the instruction.
inherited CreateSized(AAddress, ASize);
// Convert Instr arguments to Target and Source.
case Instr.Mnemonic of
mPush:
begin
FSource := ConvArgToIInstr(Instr.Arguments[1]);
FTarget := CreateRefSource(CreateRegSource(DisAsmX.rEsp, rtDWord), 4);
end;
mPop:
begin
FTarget := ConvArgToIInstr(Instr.Arguments[1]);
FSource := CreateRefSource(CreateRegSource(DisAsmX.rEsp, rtDWord), 4);
end;
else
begin
FTarget := ConvArgToIInstr(Instr.Arguments[1]);
FSource := ConvArgToIInstr(Instr.Arguments[2]);
end;
end;
if (FTarget = nil) or (FSource = nil) then
raise Exception.Create(SErrorInInstr);
end;
constructor TAssignInstr.CreateAssign(AAddress: TAddress; ASize: Integer; ATarget, ASource: IInstrSource);
begin
inherited CreateSized(AAddress, ASize);
FTarget := ATarget;
FSource := ASource;
end;
{ TRetInstr }
constructor TRetInstr.Create(AAddress: TAddress);
var
Instr: TOpcInstr;
ASize: Integer;
resourcestring
SErrorInInstr = 'Error in instruction';
begin
// Get the instruction.
Instr := GetInstruction(AAddress, ASize);
if (Instr.Mnemonic <> mRet) or (Instr.LoRepPrefix <> lrpNone) or
(Instr.SegPrefix <> spNone) or Instr.AddressSizePrefix or
(Instr.Arguments[2].ArgumentType <> atNone) or
(Instr.Arguments[3].ArgumentType <> atNone) then
raise EInstructionError.Create(SErrorInInstr);
// inherited create using the Size of the instruction.
inherited CreateSized(AAddress, ASize);
// Get PopSize from the first argument.
case Instr.Arguments[1].ArgumentType of
atNone: FPopSize := 0;
atImm: FPopSize := Instr.Arguments[1].ImmValue;
else
raise EInstructionError.Create(SErrorInInstr);
end;
end;
// Create the instrs type using GetInstruction in DisAsmX.
procedure CreateInstr(Address: TAddress; InstrOwner: IInstrOwner);
var
OpcInstr: TOpcInstr;
ASize: Integer;
Instr: TInstruction;
begin
// Default an Assembler instruction.
try
OpcInstr := GetInstruction(Address, ASize);
except
On EDisAsmError do
begin
InstrOwner.AddInstr(TAsmInstr.Create(Address));
Exit;
end;
end;
{ TODO -cAdditions : Add support other mnemonic types. }
case OpcInstr.Mnemonic of
mMov: InstrOwner.AddInstr(TAssignInstr.Create(Address));
mRet: InstrOwner.AddInstr(TRetInstr.Create(Address));
mPush:
begin
InstrOwner.AddInstr(TAssignInstr.CreateAssign(Address, 0, CreateRegSource(DisAsmX.rEsp, rtDWord),
CreateDuoSource(CreateRegSource(DisAsmX.rEsp, rtDWord), CreateConstSource(4), dstSub)));
InstrOwner.AddInstr(TAssignInstr.Create(Address));
end;
mPop:
begin
Instr := TAssignInstr.Create(Address);
InstrOwner.AddInstr(Instr);
InstrOwner.AddInstr(TAssignInstr.CreateAssign(Instr.Address + Instr.Size, 0, CreateRegSource(DisAsmX.rEsp, rtDWord),
CreateDuoSource(CreateRegSource(DisAsmX.rEsp, rtDWord), CreateConstSource(4), dstAdd)));
end;
else
InstrOwner.AddInstr(TAsmInstr.Create(Address));
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -