📄 disasm.pas
字号:
unit DisAsm;
interface
uses
SysUtils, Classes;
type
EDisAsmError = class(Exception);
TRegister = (rEax, rEcx, rEdx, rEbx, rEsp, rEbp, rEsi, rEdi);
TdaRef = record
MultiplyReg1: Integer;
ARegister1: TRegister;
MultiplyReg2: Integer;
ARegister2: TRegister;
Immidiate: PChar;
end;
TJumpInstrProc = Procedure (Param: Pointer; ValueAddress, JumpAddress: PChar; var Result: String);
TCallInstrProc = Procedure (Param: Pointer; ValueAddress, CallAddress: PChar; var Result: String);
TAddressRefProc = Procedure (Param: Pointer; ValueAddress, RefAddress: PChar; var Result: String);
TRefProc = Procedure (Param: Pointer; Ref: TdaRef; RefSize: Integer; var Result: String);
TImmidiateDataProc = Procedure (Param: Pointer; ValueAddress: PChar; OperandSize: Integer; Sigend: Boolean; var Result: String);
TDisAsm = class(TObject)
public
OnJumpInstr: TJumpInstrProc;
OnCallInstr: TCallInstrProc;
OnAddressRef: TAddressRefProc;
OnRef: TRefProc;
OnImmidiateData: TImmidiateDataProc;
Param: Pointer;
function GetInstruction(Address: PChar; var Size: Integer): String;
end;
const
ModRMReg = $38;
ModRMMod = $C0;
ModRMRM = $07;
ERROR_NOT_ENOUGH_CODE = 'Not enough code.';
ERROR_INVALID_OPERAND = 'Invalid AddrMethod and OperandType combination';
ERROR_INVALID_OPERAND_SIZE = 'Invalid OperandSize';
function SignedIntToHex(Value: Integer; Digits: Integer): String;
function FindFirstSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
function FindLastSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
implementation
uses
Windows, DisAsmTables;
function SignedIntToHex(Value: Integer; Digits: Integer): String;
begin
if Value < 0 then Result := '-$' + IntToHex(-Integer(Value), Digits)
else Result := '+$' + IntToHex(Integer(Value), Digits);
end;
function FindFirstSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
begin
Result := SearchAddress;
While Result <= SearchAddress + SearchSize - 5 do
begin
if (Result[0] = #$E8) and (Result + PInteger(Result + 1)^ + 5 = CallAddress) then
Exit;
Inc(Result);
end;
Result := nil;
end;
function FindLastSimpleCallTo(CallAddress, SearchAddress: PChar; SearchSize: Integer): PChar;
begin
Result := SearchAddress + SearchSize - 5;
While Result >= SearchAddress do
begin
if (Result[0] = #$E8) and (Result + PInteger(Result + 1)^ + 5 = CallAddress) then
Exit;
Dec(Result);
end;
Result := nil;
end;
function TDisAsm.GetInstruction(Address: PChar; var Size: Integer): String;
var
Ref: TdaRef;
function ReadDWord: DWord;
begin
if IsBadReadPtr(Address, 4) then
Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
Result := PDWord(Address + Size)^;
Inc(Size, 4);
end;
function ReadWord: Word;
begin
if IsBadReadPtr(Address, 2) then
Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
Result := PWord(Address + Size)^;
Inc(Size, 2);
end;
function ReadByte: Byte;
begin
if IsBadReadPtr(Address, 1) then
Raise EDisAsmError.Create(ERROR_NOT_ENOUGH_CODE);
Result := PByte(Address + Size)^;
Inc(Size, 1);
end;
function GetRefAddress: String;
var
RefAddress: PChar;
begin
RefAddress := PChar(ReadDWord);
Ref.Immidiate := Ref.Immidiate + Integer(RefAddress);
Result := '$' + IntToHex(DWord(RefAddress), 4);
if Assigned(OnAddressRef) then
OnAddressRef(Param, Address + Size - 4, RefAddress, Result);
Result := '^' + Chr(Length(Result)) + Result;
end;
var
XHasModRM: Boolean;
XModRM: Byte;
function ModRM: Byte;
begin
if not XHasModRM then
begin
XModRM := ReadByte;
XHasModRM := True;
end;
Result := XModRM;
end;
var
XHasSib: Boolean;
XSib: Byte;
function Sib: Byte;
begin
if not XHasSib then
begin
XSib := ReadByte;
XHasSib := True;
end;
Result := XSib;
end;
var
DeffOperandSize: Integer;
AddressSize: Integer;
OperandSize: Integer;
SegOverride: Boolean;
SegName: String;
MustHaveSize: Boolean;
function Operand(AddrMethod, OperandType, EnhOperandType: Char): String;
function GetRegName(Reg: Byte): String;
const
ByteRegs1: array[0..3] of Char = 'acdb';
ByteRegs2: array[0..1] of Char = 'lh';
WordRegs1: array[0..7] of Char = 'acdbsbsd';
WordRegs2: array[0..4] of Char = 'xxpi';
begin
if OperandSize = 1 then
Result := ByteRegs1[Reg mod 4] + ByteRegs2[Reg div 4]
else
begin
if OperandSize = 4 then Result := 'e'
else Result := '';
Result := Result + WordRegs1[Reg] + WordRegs2[Reg div 2];
end;
end;
function GetEffectiveAddress(EAMustHaveSize: Boolean): String;
var
RM: Byte;
AMod: Byte;
function ReadSib: String;
var
SI: Byte;
SS: Byte;
Base: Byte;
begin
Base := Sib and $07;
SI := (Sib shr 3) and $07;
SS := (Sib shr 6) and $03;
Case Base of
0: Result := '[eax';
1: Result := '[ecx';
2: Result := '[edx';
3: Result := '[ebx';
4: Result := '[esp';
5: if AMod <> 0 then Result := '[ebp'
else Result := '[' + GetRefAddress;
6: Result := '[esi';
7: Result := '[edi';
end;
if (Base <> 5) or (AMod = 0) then
begin
Ref.ARegister2 := TRegister(Base);
Ref.MultiplyReg2 := 1;
end;
Case SI of
0: Result := Result + '+eax';
1: Result := Result + '+ecx';
2: Result := Result + '+edx';
3: Result := Result + '+ebx';
5: Result := Result + '+ebp';
6: Result := Result + '+esi';
7: Result := Result + '+edi';
end;
if SI <> 4 then Ref.ARegister1 := TRegister(SI);
if SI <> 4 then
Case SS of
0: begin
Result := Result + '';
Ref.MultiplyReg1 := 1;
end;
1: begin
Result := Result + '*2';
Ref.MultiplyReg1 := 2;
end;
2: begin
Result := Result + '*4';
Ref.MultiplyReg1 := 4;
end;
3: begin
Result := Result + '*8';
Ref.MultiplyReg1 := 8;
end;
end;
end;
var
I: Integer;
begin
RM := ModRM and ModRMRM;
AMod := ModRm and ModRMMod shr 6;
if AMod = 3 then
begin
Result := GetRegName(RM);
Exit;
end;
Result := '%s' + Chr(OperandSize);
if SegOverride then
Result := Result + SegName + ':';
if OperandSize <> 4 then
MustHaveSize := True;
if AddressSize = 4 then
begin
if (AMod = 0) and (RM = 5) then
begin
Result := Result + '[' + GetRefAddress + ']';
if Assigned(OnRef) then OnRef(Param, Ref, OperandSize, Result);
Exit;
end;
end
else
begin
if (AMod = 0) and (RM = 6) then
begin
Result := Result + '[' + GetRefAddress + ']';
if Assigned(OnRef) then OnRef(Param, Ref, OperandSize, Result);
Exit;
end;
end;
if AddressSize = 2 then
Case RM of
0: Result := Result + '[bx+si';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -