mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-25 13:39:11 +02:00
* finished disassembler
git-svn-id: trunk@9238 -
This commit is contained in:
parent
d14455fdbc
commit
6aae9024cc
@ -36,7 +36,7 @@ unit FPWDGlobal;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Windows, FPWDType, Maps, WinDebugger;
|
SysUtils, Windows, FPWDType, Maps, WinDebugger, WinDExtra;
|
||||||
|
|
||||||
type
|
type
|
||||||
TMWDState = (dsStop, dsRun, dsPause, dsQuit, dsEvent);
|
TMWDState = (dsStop, dsRun, dsPause, dsQuit, dsEvent);
|
||||||
@ -60,6 +60,7 @@ var
|
|||||||
|
|
||||||
|
|
||||||
function GetProcess(const AID: Integer; var AProcess: TDbgProcess): Boolean;
|
function GetProcess(const AID: Integer; var AProcess: TDbgProcess): Boolean;
|
||||||
|
function FormatAddress(const AAddress): String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -70,6 +71,13 @@ begin
|
|||||||
// then Log('Unknown Process ID %u', [AID]);
|
// then Log('Unknown Process ID %u', [AID]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function FormatAddress(const AAddress): String;
|
||||||
|
const
|
||||||
|
SIZE: array[TMWDMode] of Integer = (4, 8);
|
||||||
|
begin
|
||||||
|
Result := HexValue(AAddress, SIZE[GMode], [hvfIncludeHexchar]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
_UnAligendContext: record
|
_UnAligendContext: record
|
||||||
|
@ -263,7 +263,7 @@ end;
|
|||||||
|
|
||||||
function TDbgProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
|
function TDbgProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
|
||||||
begin
|
begin
|
||||||
Result := TDbgLibrary.Create(Self, FormatAddress(AInfo.lpBaseOfDll), AInfo);
|
Result := TDbgLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo);
|
||||||
FLibMap.Add(TDbgPtr(AInfo.lpBaseOfDll), Result);
|
FLibMap.Add(TDbgPtr(AInfo.lpBaseOfDll), Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -660,7 +660,7 @@ begin
|
|||||||
Context^.ContextFlags := CONTEXT_CONTROL;
|
Context^.ContextFlags := CONTEXT_CONTROL;
|
||||||
if not GetThreadContext(Thread.Handle, Context^)
|
if not GetThreadContext(Thread.Handle, Context^)
|
||||||
then begin
|
then begin
|
||||||
Log('Break $s: Unable to get context', [FormatAddress(FLocation)]);
|
Log('Break $s: Unable to get context', [HexValue(FLocation, SizeOf(Pointer), [hvfIncludeHexchar])]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -673,7 +673,7 @@ begin
|
|||||||
|
|
||||||
if not SetThreadContext(Thread.Handle, Context^)
|
if not SetThreadContext(Thread.Handle, Context^)
|
||||||
then begin
|
then begin
|
||||||
Log('Break %s: Unable to set context', [FormatAddress(FLocation)]);
|
Log('Break %s: Unable to set context', [HexValue(FLocation, SizeOf(Pointer), [hvfIncludeHexchar])]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
Result := True;
|
Result := True;
|
||||||
|
@ -43,11 +43,16 @@ uses
|
|||||||
type
|
type
|
||||||
TDbgPtr = PtrUInt;
|
TDbgPtr = PtrUInt;
|
||||||
|
|
||||||
|
type
|
||||||
|
THexValueFormatFlag = (hvfSigned, hvfPrefixPositive, hvfIncludeHexchar);
|
||||||
|
THexValueFormatFlags = set of THexValueFormatFlag;
|
||||||
|
|
||||||
|
|
||||||
function GetLastErrorText(AErrorCode: Cardinal): String; {$IFNDEF FPC} overload; {$ENDIF}
|
function GetLastErrorText(AErrorCode: Cardinal): String; {$IFNDEF FPC} overload; {$ENDIF}
|
||||||
function GetLastErrorText: String; {$IFNDEF FPC} overload; {$ENDIF}
|
function GetLastErrorText: String; {$IFNDEF FPC} overload; {$ENDIF}
|
||||||
|
|
||||||
function FormatAddress(const P): String;
|
|
||||||
function AlignPtr(Src: Pointer; Alignment: Byte): Pointer;
|
function AlignPtr(Src: Pointer; Alignment: Byte): Pointer;
|
||||||
|
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||||
procedure Log(const AText: String; const AParams: array of const); overload;
|
procedure Log(const AText: String; const AParams: array of const); overload;
|
||||||
procedure Log(const AText: String); overload;
|
procedure Log(const AText: String); overload;
|
||||||
|
|
||||||
@ -59,23 +64,53 @@ procedure Log(const AText: String); overload;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, FPWDGLobal;
|
SysUtils;
|
||||||
|
|
||||||
//function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall; external 'kernel32';
|
//function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall; external 'kernel32';
|
||||||
//function Wow64GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL; stdcall; external 'kernel32';
|
//function Wow64GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL; stdcall; external 'kernel32';
|
||||||
|
|
||||||
|
|
||||||
function FormatAddress(const P): String;
|
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
||||||
|
var
|
||||||
|
i: Int64;
|
||||||
|
p: PByte;
|
||||||
begin
|
begin
|
||||||
case GMode of
|
if ASize > 8
|
||||||
dm32: Result := '$' + IntToHex(DWord(p), 8);
|
then begin
|
||||||
dm64: Result := '$' + IntToHex(int64(p), 16);
|
Result := 'HexValue: size to large';
|
||||||
else
|
Exit;
|
||||||
Result := 'Unknown mode';
|
end;
|
||||||
|
if ASize = 0
|
||||||
|
then begin
|
||||||
|
Result := '';
|
||||||
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
p := @AValue;
|
||||||
|
if p[ASize - 1] < $80
|
||||||
|
then Exclude(AFlags, hvfSigned);
|
||||||
|
|
||||||
|
if hvfSigned in AFlags
|
||||||
|
then i := -1
|
||||||
|
else i := 0;
|
||||||
|
|
||||||
|
Move(AValue, i, ASize);
|
||||||
|
if hvfSigned in AFlags
|
||||||
|
then begin
|
||||||
|
i := not i + 1;
|
||||||
|
Result := '-';
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if hvfPrefixPositive in AFlags
|
||||||
|
then Result := '+';
|
||||||
|
end;
|
||||||
|
if hvfIncludeHexchar in AFlags
|
||||||
|
then Result := Result + '$';
|
||||||
|
|
||||||
|
Result := Result + HexStr(i, ASize * 2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function GetLastErrorText: String;
|
function GetLastErrorText: String;
|
||||||
begin
|
begin
|
||||||
Result := GetLastErrorText(GetLastError);
|
Result := GetLastErrorText(GetLastError);
|
||||||
|
@ -36,6 +36,7 @@ unit WinDisas;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
{.$define debug_OperandSize}
|
{.$define debug_OperandSize}
|
||||||
|
{.$define verbose_string_instructions}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
SysUtils, Windows, WindExtra;
|
SysUtils, Windows, WindExtra;
|
||||||
@ -53,8 +54,9 @@ uses
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
procedure Disassemble(var AAddress: Pointer; const A64Bit: Boolean; out ACodeBytes: String; out ACode: String);
|
||||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr): String;
|
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||||
|
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr): String;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -62,76 +64,64 @@ type
|
|||||||
TFlag = (flagRex, flagSib, flagModRM, rexB, rexX, rexR, rexW, preOpr, preAdr, preLock, preRep{N}, preRepNE);
|
TFlag = (flagRex, flagSib, flagModRM, rexB, rexX, rexR, rexW, preOpr, preAdr, preLock, preRep{N}, preRepNE);
|
||||||
TFlags = set of TFlag;
|
TFlags = set of TFlag;
|
||||||
|
|
||||||
TOperandSize = (os8, os16, os32, os64, os80);
|
// Keep 8,16,32,64 together
|
||||||
|
TOperandSize = (os8, os16, os32, os64, os48, os80, os128);
|
||||||
TAddressSize = (as16, as32, as64);
|
TAddressSize = (as16, as32, as64);
|
||||||
TRegisterType = (reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug);
|
TRegisterType = (reg0, reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug, regX87);
|
||||||
|
TModRMType = (modReg, modMem);
|
||||||
|
TModRMTypes = set of TModRMType;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
ADDRESS_BYTES: array[TAddressSize] of Byte = (2, 4, 8);
|
ADDRESS_BYTES: array[TAddressSize] of Byte = (2, 4, 8);
|
||||||
OPERAND_BYTES: array[TOperandSize] of Byte = (1, 2, 4, 8, 10);
|
OPERAND_BYTES: array[TOperandSize] of Byte = (1, 2, 4, 8, 6, 10, 16);
|
||||||
OPERAND_REG: array[os8..os64] of TRegisterType = (reg8, reg16, reg32, reg64);
|
OPERAND_REG: array[os8..os64] of TRegisterType = (reg8, reg16, reg32, reg64);
|
||||||
|
STD_REGS = [reg8..reg64];
|
||||||
|
|
||||||
type
|
type
|
||||||
THexValueFormatFlag = (hvfSigned, hvfPrefixPositive, hvfIncludeHexchar);
|
TOperandFlag = (ofMemory);
|
||||||
THexValueFormatFlags = set of THexValueFormatFlag;
|
TOperandFlags = set of TOperandFlag;
|
||||||
|
|
||||||
function HexValue(const AValue; ASize: Byte; AFlags: THexValueFormatFlags): String;
|
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr): String;
|
||||||
var
|
|
||||||
i: Int64;
|
|
||||||
p: PByte;
|
|
||||||
begin
|
|
||||||
if ASize > 8
|
|
||||||
then begin
|
|
||||||
Result := 'HexValue: size to large';
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
if ASize = 0
|
|
||||||
then begin
|
|
||||||
Result := '';
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
p := @AValue;
|
|
||||||
if p[ASize - 1] < $80
|
|
||||||
then Exclude(AFlags, hvfSigned);
|
|
||||||
|
|
||||||
if hvfSigned in AFlags
|
|
||||||
then i := -1
|
|
||||||
else i := 0;
|
|
||||||
|
|
||||||
Move(AValue, i, ASize);
|
|
||||||
if hvfSigned in AFlags
|
|
||||||
then begin
|
|
||||||
i := not i + 1;
|
|
||||||
Result := '-';
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if hvfPrefixPositive in AFlags
|
|
||||||
then Result := '+';
|
|
||||||
end;
|
|
||||||
if hvfIncludeHexchar in AFlags
|
|
||||||
then Result := Result + '$';
|
|
||||||
|
|
||||||
Result := Result + HexStr(i, ASize * 2);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr): String;
|
|
||||||
var
|
var
|
||||||
S: String;
|
S: String;
|
||||||
begin
|
begin
|
||||||
Disassemble(AProcess, A64bit, Address, S, Result);
|
Disassemble(AProcess, A64bit, AAddress, S, Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var Address: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
procedure Disassemble(const AProcess: Handle; const A64Bit: Boolean; var AAddress: TDbgPtr; out ACodeBytes: String; out ACode: String);
|
||||||
|
const
|
||||||
|
PTRSIZE: array[Boolean] of Byte = (4, 8);
|
||||||
var
|
var
|
||||||
|
BytesRead: Cardinal;
|
||||||
Code: array[0..20] of Byte;
|
Code: array[0..20] of Byte;
|
||||||
|
p: Pointer;
|
||||||
|
begin
|
||||||
|
BytesRead := 0;
|
||||||
|
if not ReadProcessMemory(AProcess, Pointer(AAddress), @Code, SizeOf(Code), BytesRead) and (BytesRead = SizeOf(Code))
|
||||||
|
then begin
|
||||||
|
Log('Disassemble: Failed to read memory at %s, got %u bytes', [HexValue(AAddress, PTRSIZE[A64Bit], [hvfIncludeHexchar]), BytesRead]);
|
||||||
|
ACode := '??';
|
||||||
|
ACodeBytes := '??';
|
||||||
|
Inc(AAddress);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
p := @Code;
|
||||||
|
Disassemble(p, A64Bit, ACodeBytes, ACode);
|
||||||
|
Inc(AAddress, PtrUInt(p) - PtrUInt(@Code));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Disassemble(var AAddress: Pointer; const A64Bit: Boolean; out ACodeBytes: String; out ACode: String);
|
||||||
|
var
|
||||||
|
Code: PByte;
|
||||||
CodeIdx: Byte;
|
CodeIdx: Byte;
|
||||||
Operand: array[1..4] of record
|
Operand: array[1..4] of record
|
||||||
Value: String;
|
Value: String;
|
||||||
Size: TOperandSize;
|
Size: TOperandSize;
|
||||||
ByteCount: Byte;
|
ByteCount: Byte;
|
||||||
|
ByteCount2: Byte;
|
||||||
FormatFlags: THexValueFormatFlags;
|
FormatFlags: THexValueFormatFlags;
|
||||||
IsMemory: Boolean;
|
Flags: TOperandFlags;
|
||||||
end;
|
end;
|
||||||
OperIdx: Byte;
|
OperIdx: Byte;
|
||||||
ModRMIdx: Byte;
|
ModRMIdx: Byte;
|
||||||
@ -170,14 +160,14 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := True;
|
Result := True;
|
||||||
for n := 1 to OperIdx do
|
for n := 1 to OperIdx do
|
||||||
if Operand[n].IsMemory then Exit;
|
if ofMemory in Operand[n].Flags then Exit;
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
begin
|
begin
|
||||||
if (preLock in Flags) and CheckMem
|
if (preLock in Flags) and CheckMem
|
||||||
then begin
|
then begin
|
||||||
Exclude(Flags, preLock);
|
Exclude(Flags, preLock);
|
||||||
Result := 'lock: ' + AOpcode;
|
Result := 'lock ' + AOpcode;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
Result := AOpcode;
|
Result := AOpcode;
|
||||||
@ -188,7 +178,7 @@ var
|
|||||||
if preRep in Flags
|
if preRep in Flags
|
||||||
then begin
|
then begin
|
||||||
Exclude(Flags, preRep);
|
Exclude(Flags, preRep);
|
||||||
Result := 'rep: ' + AOpcode;
|
Result := 'rep ' + AOpcode;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
Result := AOpcode;
|
Result := AOpcode;
|
||||||
@ -199,13 +189,13 @@ var
|
|||||||
if preRep in Flags
|
if preRep in Flags
|
||||||
then begin
|
then begin
|
||||||
Exclude(Flags, preRep);
|
Exclude(Flags, preRep);
|
||||||
Result := 'repe: ' + AOpcode;
|
Result := 'repe ' + AOpcode;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
if preRepNE in Flags
|
if preRepNE in Flags
|
||||||
then begin
|
then begin
|
||||||
Exclude(Flags, preRepNE);
|
Exclude(Flags, preRepNE);
|
||||||
Result := 'repe: ' + AOpcode;
|
Result := 'repne ' + AOpcode;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
Result := AOpcode;
|
Result := AOpcode;
|
||||||
@ -274,7 +264,7 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddOperand(const AValue: String; ASize: TOperandSize; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AIsMemory: Boolean = False);
|
procedure AddOperand(const AValue: String; ASize: TOperandSize; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AFlags: TOperandFlags = []; AByteCount2: Byte = 0);
|
||||||
begin
|
begin
|
||||||
Inc(OperIdx);
|
Inc(OperIdx);
|
||||||
if OperIdx > High(Operand)
|
if OperIdx > High(Operand)
|
||||||
@ -285,14 +275,15 @@ var
|
|||||||
|
|
||||||
Operand[OperIdx].Size := ASize;
|
Operand[OperIdx].Size := ASize;
|
||||||
Operand[OperIdx].ByteCount := AByteCount;
|
Operand[OperIdx].ByteCount := AByteCount;
|
||||||
|
Operand[OperIdx].ByteCount2 := AByteCount2;
|
||||||
Operand[OperIdx].FormatFlags := AFormatFlags;
|
Operand[OperIdx].FormatFlags := AFormatFlags;
|
||||||
Operand[OperIdx].Value := AValue;
|
Operand[OperIdx].Value := AValue;
|
||||||
Operand[OperIdx].IsMemory := AIsMemory;
|
Operand[OperIdx].Flags := AFlags;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddOperand(const AValue: String; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AIsMemory: Boolean = False);
|
procedure AddOperand(const AValue: String; AByteCount: Byte = 0; AFormatFlags: THexValueFormatFlags = []; AFlags: TOperandFlags = []);
|
||||||
begin
|
begin
|
||||||
AddOperand(AValue, OperandSize32, AByteCount, AFormatFlags, AIsMemory);
|
AddOperand(AValue, OperandSize32, AByteCount, AFormatFlags, AFlags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function SizeReg32(const AReg: String; ASize: TOperandSize): String;
|
function SizeReg32(const AReg: String; ASize: TOperandSize): String;
|
||||||
@ -345,6 +336,9 @@ var
|
|||||||
then Result := Format('r%d', [8 + AIndex]) + POSTFIX[AType]
|
then Result := Format('r%d', [8 + AIndex]) + POSTFIX[AType]
|
||||||
else Result := SizeReg32(REGS[AIndex], OSMAP[AType]);
|
else Result := SizeReg32(REGS[AIndex], OSMAP[AType]);
|
||||||
end;
|
end;
|
||||||
|
regX87: begin
|
||||||
|
Result := Format('st(%d)', [AIndex]);
|
||||||
|
end;
|
||||||
regMmx: begin
|
regMmx: begin
|
||||||
Result := Format('mmx%d', [AIndex]);
|
Result := Format('mmx%d', [AIndex]);
|
||||||
end;
|
end;
|
||||||
@ -370,22 +364,42 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := StdReg(AIndex, OPERAND_REG[OperandSize32], rexR in Flags);
|
Result := StdReg(AIndex, OPERAND_REG[OperandSize32], rexR in Flags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure AddStdReg(AIndex: Byte; AType: TRegisterType; AExtReg: Boolean);
|
||||||
|
const
|
||||||
|
// reg8, reg16, reg32, reg64, regMmx, regXmm, regSegment, regControl, regDebug, regX87
|
||||||
|
REGSIZE: array[Boolean, reg8..High(TRegisterType)] of TOperandSize = (
|
||||||
|
{32}(os8, os16, os32, os64, os64, os128, os16, os32, os32, os80),
|
||||||
|
{64}(os8, os16, os32, os64, os64, os128, os16, os64, os64, os80)
|
||||||
|
);
|
||||||
|
begin
|
||||||
|
AddOperand(StdReg(AIndex, AType, AExtReg), REGSIZE[A64Bit, AType]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AddStdReg(AIndex: Byte);
|
||||||
|
begin
|
||||||
|
AddOperand(StdReg(AIndex, OPERAND_REG[OperandSize32], rexR in Flags));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AddModReg(AType: TRegisterType; ASize: TOperandSize);
|
||||||
|
begin
|
||||||
|
Include(Flags, flagModRM);
|
||||||
|
AddOperand(StdReg(Code[ModRMIdx] shr 3, AType, False), ASize);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure AddModReg(AType: TRegisterType; AExtReg: Boolean);
|
procedure AddModReg(AType: TRegisterType; AExtReg: Boolean);
|
||||||
begin
|
begin
|
||||||
Include(Flags, flagModRM);
|
Include(Flags, flagModRM);
|
||||||
AddOperand(StdReg((Code[ModRMIdx] shr 3), AType, AExtReg));
|
AddStdReg(Code[ModRMIdx] shr 3, AType, AExtReg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddModReg;
|
procedure AddModReg;
|
||||||
begin
|
begin
|
||||||
Include(Flags, flagModRM);
|
Include(Flags, flagModRM);
|
||||||
AddOperand(StdReg((Code[ModRMIdx] shr 3), OPERAND_REG[OperandSize32], rexR in Flags));
|
AddStdReg(Code[ModRMIdx] shr 3);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure AddModRM(AReqTypes: TModRMTypes; ASize: TOperandSize; AType: TRegisterType);
|
||||||
procedure AddModRM(AAllowReg, AAllowMem: Boolean; ASize: TOperandSize);
|
|
||||||
var
|
var
|
||||||
Mode, Rm: Byte;
|
Mode, Rm: Byte;
|
||||||
procedure Mem16;
|
procedure Mem16;
|
||||||
@ -395,11 +409,11 @@ var
|
|||||||
case Mode of
|
case Mode of
|
||||||
0: begin
|
0: begin
|
||||||
if rm = 6 // disp16 -> exeption to the regs
|
if rm = 6 // disp16 -> exeption to the regs
|
||||||
then AddOperand('%s', ASize, 2, [hvfSigned, hvfIncludeHexchar], True)
|
then AddOperand('%s', ASize, 2, [hvfSigned, hvfIncludeHexchar], [ofMemory])
|
||||||
else AddOperand(REGS16[rm], ASize, 0, [], True);
|
else AddOperand(REGS16[rm], ASize, 0, [], [ofMemory]);
|
||||||
end;
|
end;
|
||||||
1: AddOperand(REGS16[rm] + '%s', ASize, 1, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], True);
|
1: AddOperand(REGS16[rm] + '%s', ASize, 1, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], [ofMemory]);
|
||||||
2: AddOperand(REGS16[rm] + '%s', ASize, 2, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], True);
|
2: AddOperand(REGS16[rm] + '%s', ASize, 2, [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar], [ofMemory]);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -421,16 +435,16 @@ var
|
|||||||
// Check for reg (mode = 3) first;
|
// Check for reg (mode = 3) first;
|
||||||
if mode = 3
|
if mode = 3
|
||||||
then begin
|
then begin
|
||||||
if not AAllowReg
|
if modReg in AReqTypes
|
||||||
then AddOperand('**')
|
then AddStdReg(rm, AType, False)
|
||||||
else AddOperand(StdReg(rm, OPERAND_REG[ASize], False), ASize);
|
else AddOperand('**');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Check if mem is allowed
|
// Check if mem is allowed
|
||||||
if not AAllowMem
|
if not (modMem in AReqTypes)
|
||||||
then begin
|
then begin
|
||||||
AddOperand('**', 0, [], True);
|
AddOperand('**', 0, [], [ofMemory]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -520,13 +534,15 @@ var
|
|||||||
Oper.Flags := [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar];
|
Oper.Flags := [hvfSigned, hvfPrefixPositive, hvfIncludeHexchar];
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
AddOperand(Oper.Value, ASize, Oper.Size, Oper.Flags, True);
|
AddOperand(Oper.Value, ASize, Oper.Size, Oper.Flags, [ofMemory]);
|
||||||
end;
|
end;
|
||||||
//===================
|
//===================
|
||||||
|
|
||||||
procedure AddAp;
|
procedure AddAp;
|
||||||
begin
|
begin
|
||||||
AddOperand('Ap');
|
if OperandSize32 = os16 //XXXX:XXXX
|
||||||
|
then AddOperand('$%1:s:%0:s', os32, 2, [], [], 2)
|
||||||
|
else AddOperand('$%1:s:%0:s', os48, 4, [], [], 2)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddCd_q;
|
procedure AddCd_q;
|
||||||
@ -541,29 +557,29 @@ var
|
|||||||
|
|
||||||
procedure AddEb;
|
procedure AddEb;
|
||||||
begin
|
begin
|
||||||
AddModRM(True, True, os8);
|
AddModRM([modReg, modMem], os8, reg8);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddEd;
|
procedure AddEd;
|
||||||
begin
|
begin
|
||||||
AddModRM(True, True, os32);
|
AddModRM([modReg, modMem], os32, reg32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddEd_q;
|
procedure AddEd_q;
|
||||||
begin
|
begin
|
||||||
if flagRex in Flags
|
if flagRex in Flags
|
||||||
then AddModRM(True, True, os64)
|
then AddModRM([modReg, modMem], os64, reg64)
|
||||||
else AddModRM(True, True, os32);
|
else AddModRM([modReg, modMem], os32, reg32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddEv;
|
procedure AddEv;
|
||||||
begin
|
begin
|
||||||
AddModRM(True, True, OperandSize32);
|
AddModRM([modReg, modMem], OperandSize32, OPERAND_REG[OperandSize32]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddEw;
|
procedure AddEw;
|
||||||
begin
|
begin
|
||||||
AddModRM(True, True, os16);
|
AddModRM([modReg, modMem], os16, reg16);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddFv;
|
procedure AddFv;
|
||||||
@ -646,92 +662,104 @@ var
|
|||||||
|
|
||||||
procedure AddM;
|
procedure AddM;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, OperandSize32);
|
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMa;
|
procedure AddMa;
|
||||||
begin
|
begin
|
||||||
AddOperand('Ma');
|
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMb;
|
procedure AddMb;
|
||||||
begin
|
begin
|
||||||
AddOperand('Ma');
|
AddModRM([modMem], os8, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMd;
|
procedure AddMd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Md');
|
AddModRM([modMem], os32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMd_q;
|
procedure AddMd_q;
|
||||||
begin
|
begin
|
||||||
AddOperand('Md/q');
|
if flagRex in Flags
|
||||||
|
then AddModRM([modMem], os64, reg0 {dont care})
|
||||||
|
else AddModRM([modMem], os32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMdq;
|
procedure AddMdq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Mdq');
|
AddModRM([modMem], os128, reg0 {dont care})
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMp;
|
procedure AddMp;
|
||||||
begin
|
begin
|
||||||
AddOperand('Mp');
|
if OperandSize32 = os16 //XXXX:XXXX
|
||||||
|
then AddModRM([modMem], os32, reg0 {dont care})
|
||||||
|
else AddModRM([modMem], os48, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMq;
|
procedure AddMq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Mq');
|
AddModRM([modMem], os64, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMs;
|
procedure AddMs;
|
||||||
begin
|
begin
|
||||||
AddOperand('Ms');
|
if A64Bit
|
||||||
|
then AddModRM([modMem], os80, reg0 {dont care})
|
||||||
|
else AddModRM([modMem], os48, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMw_Rv;
|
procedure AddMw_Rv;
|
||||||
begin
|
begin
|
||||||
AddOperand('Mw/Rv');
|
if Code[ModRMIdx] shr 6 = 3 // mode = 3 -> reg
|
||||||
|
then AddModRM([modReg], OperandSize32, OPERAND_REG[OperandSize32])
|
||||||
|
else AddModRM([modMem], os16, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddOb;
|
procedure AddOb;
|
||||||
begin
|
begin
|
||||||
AddOperand('%s', os8, ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], True)
|
AddOperand('%s', os8, ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], [ofMemory])
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddOv;
|
procedure AddOv;
|
||||||
begin
|
begin
|
||||||
AddOperand('%s', ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], True)
|
AddOperand('%s', ADDRESS_BYTES[AddressSize32], [hvfIncludeHexchar], [ofMemory])
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddPd_q;
|
procedure AddPd_q;
|
||||||
begin
|
begin
|
||||||
AddOperand('Pd/q');
|
if flagRex in Flags
|
||||||
|
then AddModReg(regMmx, os64)
|
||||||
|
else AddModReg(regMmx, os32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddPq;
|
procedure AddPq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Pq');
|
AddModReg(regMmx, False);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddPRq;
|
procedure AddPRq;
|
||||||
begin
|
begin
|
||||||
AddOperand('PRq');
|
AddModRM([modReg], os64, regMmx);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddQd;
|
procedure AddQd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Qd');
|
AddModRM([modReg, modMem], os32, regMmx);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddQq;
|
procedure AddQq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Qq');
|
AddModRM([modReg, modMem], os64, regMmx);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddRd_q;
|
procedure AddRd_q;
|
||||||
begin
|
begin
|
||||||
AddModRM(True, False, OperandSize32);
|
if A64Bit
|
||||||
|
then AddModRM([modReg], os64, reg64)
|
||||||
|
else AddModRM([modReg], os32, reg32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddSw;
|
procedure AddSw;
|
||||||
@ -741,99 +769,102 @@ var
|
|||||||
|
|
||||||
procedure AddVd_q;
|
procedure AddVd_q;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vd/q');
|
if flagRex in Flags
|
||||||
|
then AddModReg(regXmm, os64)
|
||||||
|
else AddModReg(regXmm, os32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVdq;
|
procedure AddVdq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vdq');
|
AddModReg(regXmm, os128);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVdq_sd;
|
procedure AddVdq_sd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vdq/sd');
|
AddModReg(regXmm, os64); // only lower 64 bit
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVdq_ss;
|
procedure AddVdq_ss;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vdq/ss');
|
AddModReg(regXmm, os32); // only lower 32 bit
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVpd;
|
procedure AddVpd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vsd');
|
AddModReg(regXmm, os128);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVps;
|
procedure AddVps;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vps');
|
AddModReg(regXmm, os128);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVq;
|
procedure AddVq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vq');
|
AddModReg(regXmm, os64);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVsd;
|
procedure AddVsd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vsd');
|
AddModReg(regXmm, os64);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVss;
|
procedure AddVss;
|
||||||
begin
|
begin
|
||||||
AddOperand('Vss');
|
AddModReg(regXmm, os32);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVRdq;
|
procedure AddVRdq;
|
||||||
begin
|
begin
|
||||||
AddOperand('VRdq');
|
AddModRM([modReg], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVRpd;
|
procedure AddVRpd;
|
||||||
begin
|
begin
|
||||||
AddOperand('VRpd');
|
AddModRM([modReg], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVRps;
|
procedure AddVRps;
|
||||||
begin
|
begin
|
||||||
AddOperand('VRps');
|
AddModRM([modReg], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddVRq;
|
procedure AddVRq;
|
||||||
begin
|
begin
|
||||||
AddOperand('VRq');
|
AddModRM([modReg], os64, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWdq;
|
procedure AddWdq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wdq');
|
AddModRM([modReg, modMem], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWpd;
|
procedure AddWpd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wpd');
|
AddModRM([modReg, modMem], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWps;
|
procedure AddWps;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wps');
|
AddModRM([modReg, modMem], os128, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWq;
|
procedure AddWq;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wq');
|
AddModRM([modReg, modMem], os64, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWsd;
|
procedure AddWsd;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wsd');
|
AddModRM([modReg, modMem], os64, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddWss;
|
procedure AddWss;
|
||||||
begin
|
begin
|
||||||
AddOperand('Wss');
|
AddModRM([modReg, modMem], os32, regXmm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
procedure AddXb;
|
procedure AddXb;
|
||||||
begin
|
begin
|
||||||
AddOperand('Xb');
|
AddOperand('Xb');
|
||||||
@ -863,7 +894,7 @@ var
|
|||||||
begin
|
begin
|
||||||
AddOperand('Yz');
|
AddOperand('Yz');
|
||||||
end;
|
end;
|
||||||
|
{$endif}
|
||||||
//===================
|
//===================
|
||||||
|
|
||||||
procedure AddStdOperands(AIndex: Byte);
|
procedure AddStdOperands(AIndex: Byte);
|
||||||
@ -892,32 +923,32 @@ var
|
|||||||
|
|
||||||
procedure AddMem14_28Env;
|
procedure AddMem14_28Env;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, OperandSize32);
|
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMem98_108Env;
|
procedure AddMem98_108Env;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, OperandSize32);
|
AddModRM([modMem], OperandSize32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMem16;
|
procedure AddMem16;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, os16);
|
AddModRM([modMem], os16, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMem32;
|
procedure AddMem32;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, os32);
|
AddModRM([modMem], os32, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMem64;
|
procedure AddMem64;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, os64);
|
AddModRM([modMem], os64, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddMem80;
|
procedure AddMem80;
|
||||||
begin
|
begin
|
||||||
AddModRM(False, True, os80);
|
AddModRM([modMem], os80, reg0 {dont care});
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddReg(AIndex: Byte);
|
procedure AddReg(AIndex: Byte);
|
||||||
@ -1128,6 +1159,7 @@ var
|
|||||||
for n := 1 to OperIdx do
|
for n := 1 to OperIdx do
|
||||||
begin
|
begin
|
||||||
Inc(idx, Operand[n].ByteCount);
|
Inc(idx, Operand[n].ByteCount);
|
||||||
|
Inc(idx, Operand[n].ByteCount2);
|
||||||
end;
|
end;
|
||||||
// now we can lookup the opcode
|
// now we can lookup the opcode
|
||||||
case Code[CodeIdx + idx] of
|
case Code[CodeIdx + idx] of
|
||||||
@ -1701,7 +1733,7 @@ var
|
|||||||
// it is specified as Mq or VRq
|
// it is specified as Mq or VRq
|
||||||
// So when getting Wq, we Add both and know the type
|
// So when getting Wq, we Add both and know the type
|
||||||
AddVps; AddWq;
|
AddVps; AddWq;
|
||||||
if Operand[2].IsMemory
|
if ofMemory in Operand[2].Flags
|
||||||
then Opcode := 'movlps';
|
then Opcode := 'movlps';
|
||||||
end;
|
end;
|
||||||
1: begin AddVps; AddWps; end;
|
1: begin AddVps; AddWps; end;
|
||||||
@ -1738,7 +1770,7 @@ var
|
|||||||
// it is specified as Mq or VRq
|
// it is specified as Mq or VRq
|
||||||
// So when getting Wq, we Add both and know the type
|
// So when getting Wq, we Add both and know the type
|
||||||
AddVps; AddWq;
|
AddVps; AddWq;
|
||||||
if Operand[2].IsMemory
|
if ofMemory in Operand[2].Flags
|
||||||
then Opcode := 'movhps';
|
then Opcode := 'movhps';
|
||||||
end;
|
end;
|
||||||
1: begin AddVps; AddWps; end;
|
1: begin AddVps; AddWps; end;
|
||||||
@ -2271,7 +2303,7 @@ var
|
|||||||
end;
|
end;
|
||||||
$C8..$CF: begin
|
$C8..$CF: begin
|
||||||
Opcode := 'bswp';
|
Opcode := 'bswp';
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
end;
|
end;
|
||||||
//---
|
//---
|
||||||
$D0: begin
|
$D0: begin
|
||||||
@ -2481,7 +2513,7 @@ var
|
|||||||
Include(Flags, flagRex);
|
Include(Flags, flagRex);
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
if Code[CodeIdx] <= $47
|
if Code[CodeIdx] <= $47
|
||||||
then Opcode := CheckLock('inc')
|
then Opcode := CheckLock('inc')
|
||||||
else Opcode := CheckLock('dec');
|
else Opcode := CheckLock('dec');
|
||||||
@ -2490,11 +2522,11 @@ var
|
|||||||
//---
|
//---
|
||||||
$50..$57: begin
|
$50..$57: begin
|
||||||
Opcode := 'push';
|
Opcode := 'push';
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
end;
|
end;
|
||||||
$58..$5F: begin
|
$58..$5F: begin
|
||||||
Opcode := 'pop';
|
Opcode := 'pop';
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
end;
|
end;
|
||||||
//---
|
//---
|
||||||
$60: begin
|
$60: begin
|
||||||
@ -2552,27 +2584,35 @@ var
|
|||||||
end;
|
end;
|
||||||
$6C: begin
|
$6C: begin
|
||||||
Opcode := CheckRepeat('insb');
|
Opcode := CheckRepeat('insb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYb;
|
AddYb;
|
||||||
AddOperand('dx', os16);
|
AddOperand('dx', os16);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$6D: begin
|
$6D: begin
|
||||||
if OperandSize32 = os16
|
if OperandSize32 = os16
|
||||||
then Opcode := CheckRepeat('insw')
|
then Opcode := CheckRepeat('insw')
|
||||||
else Opcode := CheckRepeat('insd');
|
else Opcode := CheckRepeat('insd');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYz;
|
AddYz;
|
||||||
AddOperand('dx', os16);
|
AddOperand('dx', os16);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$6E: begin
|
$6E: begin
|
||||||
Opcode := CheckRepeat('outsb');
|
Opcode := CheckRepeat('outsb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand('dx', os16);
|
AddOperand('dx', os16);
|
||||||
AddXb;
|
AddXb;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$6F: begin
|
$6F: begin
|
||||||
if OperandSize32 = os16
|
if OperandSize32 = os16
|
||||||
then Opcode := CheckRepeat('outsw')
|
then Opcode := CheckRepeat('outsw')
|
||||||
else Opcode := CheckRepeat('outsd');
|
else Opcode := CheckRepeat('outsd');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand('dx', os16);
|
AddOperand('dx', os16);
|
||||||
AddXz;
|
AddXz;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$70..$7F: begin
|
$70..$7F: begin
|
||||||
Opcode := 'j' + StdCond(Code[CodeIdx]);
|
Opcode := 'j' + StdCond(Code[CodeIdx]);
|
||||||
@ -2623,7 +2663,7 @@ var
|
|||||||
then Opcode := 'nop'
|
then Opcode := 'nop'
|
||||||
else begin
|
else begin
|
||||||
Opcode := 'xchg';
|
Opcode := 'xchg';
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
AddOperand(SizeReg32('ax'));
|
AddOperand(SizeReg32('ax'));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2697,7 +2737,9 @@ var
|
|||||||
end;
|
end;
|
||||||
$A4: begin
|
$A4: begin
|
||||||
Opcode := CheckRepeat('movsb');
|
Opcode := CheckRepeat('movsb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYb; AddXb;
|
AddYb; AddXb;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$A5: begin
|
$A5: begin
|
||||||
case OperandSize32 of
|
case OperandSize32 of
|
||||||
@ -2706,12 +2748,15 @@ var
|
|||||||
else
|
else
|
||||||
Opcode := CheckRepeat('movsw');
|
Opcode := CheckRepeat('movsw');
|
||||||
end;
|
end;
|
||||||
AddYv;
|
{$ifdef verbose_string_instructions}
|
||||||
AddXv;
|
AddYv; AddXv;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$A6: begin
|
$A6: begin
|
||||||
Opcode := CheckRepeatX('cmpsb');
|
Opcode := CheckRepeatX('cmpsb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddXb; AddYb;
|
AddXb; AddYb;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$A7: begin
|
$A7: begin
|
||||||
case OperandSize32 of
|
case OperandSize32 of
|
||||||
@ -2720,7 +2765,9 @@ var
|
|||||||
else
|
else
|
||||||
Opcode := CheckRepeatX('cmpsw');
|
Opcode := CheckRepeatX('cmpsw');
|
||||||
end;
|
end;
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYv; AddXv;
|
AddYv; AddXv;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$A8: begin
|
$A8: begin
|
||||||
Opcode := 'test';
|
Opcode := 'test';
|
||||||
@ -2734,8 +2781,10 @@ var
|
|||||||
end;
|
end;
|
||||||
$AA: begin
|
$AA: begin
|
||||||
Opcode := CheckRepeat('stosb');
|
Opcode := CheckRepeat('stosb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYb;
|
AddYb;
|
||||||
AddOperand('al', os8);
|
AddOperand('al', os8);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$AB: begin
|
$AB: begin
|
||||||
case OperandSize32 of
|
case OperandSize32 of
|
||||||
@ -2744,13 +2793,17 @@ var
|
|||||||
else
|
else
|
||||||
Opcode := CheckRepeat('stosw');
|
Opcode := CheckRepeat('stosw');
|
||||||
end;
|
end;
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddYv;
|
AddYv;
|
||||||
AddOperand(SizeReg32('ax'));
|
AddOperand(SizeReg32('ax'));
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$AC: begin
|
$AC: begin
|
||||||
Opcode := CheckRepeat('lodsb');
|
Opcode := CheckRepeat('lodsb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand('al', os8);
|
AddOperand('al', os8);
|
||||||
AddXb;
|
AddXb;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$AD: begin
|
$AD: begin
|
||||||
case OperandSize32 of
|
case OperandSize32 of
|
||||||
@ -2759,13 +2812,17 @@ var
|
|||||||
else
|
else
|
||||||
Opcode := CheckRepeat('lodsw');
|
Opcode := CheckRepeat('lodsw');
|
||||||
end;
|
end;
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand(SizeReg32('ax'));
|
AddOperand(SizeReg32('ax'));
|
||||||
AddXv;
|
AddXv;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$AE: begin
|
$AE: begin
|
||||||
Opcode := CheckRepeatX('scasb');
|
Opcode := CheckRepeatX('scasb');
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand('al', os8);
|
AddOperand('al', os8);
|
||||||
AddYb;
|
AddYb;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
$AF: begin
|
$AF: begin
|
||||||
case OperandSize32 of
|
case OperandSize32 of
|
||||||
@ -2774,18 +2831,20 @@ var
|
|||||||
else
|
else
|
||||||
Opcode := CheckRepeatX('scasw');
|
Opcode := CheckRepeatX('scasw');
|
||||||
end;
|
end;
|
||||||
|
{$ifdef verbose_string_instructions}
|
||||||
AddOperand(SizeReg32('ax'));
|
AddOperand(SizeReg32('ax'));
|
||||||
AddYv;
|
AddYv;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
//---
|
//---
|
||||||
$B0..$B7: begin
|
$B0..$B7: begin
|
||||||
Opcode := 'mov';
|
Opcode := 'mov';
|
||||||
AddOperand(StdReg(Code[CodeIdx], reg8, rexR in Flags), os8);
|
AddStdReg(Code[CodeIdx], reg8, rexR in Flags);
|
||||||
AddIb;
|
AddIb;
|
||||||
end;
|
end;
|
||||||
$B8..$BF: begin
|
$B8..$BF: begin
|
||||||
Opcode := 'mov';
|
Opcode := 'mov';
|
||||||
AddOperand(StdReg(Code[CodeIdx]));
|
AddStdReg(Code[CodeIdx]);
|
||||||
AddIv;
|
AddIv;
|
||||||
end;
|
end;
|
||||||
//---
|
//---
|
||||||
@ -2984,33 +3043,25 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Inc(CodeIdx);
|
Inc(CodeIdx);
|
||||||
if CodeIdx > High(Code)
|
if CodeIdx > 16 // max instruction length
|
||||||
then begin
|
then begin
|
||||||
Log('Disassemble: instruction longer than %d bytes', [SizeOf(Code)]);
|
Log('Disassemble: instruction longer than 16 bytes');
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
until Opcode <> '';
|
until Opcode <> '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
MEMPTR: array[TOperandSize] of string = ('byte ptr ', 'word ptr ', 'dword ptr ', 'qword ptr ', 'tbyte ptr ');
|
MEMPTR: array[TOperandSize] of string = ('byte ptr ', 'word ptr ', 'dword ptr ', 'qword ptr ', '', 'tbyte ptr ', '16byte ptr ');
|
||||||
OSTEXT: array[TOperandSize] of string = ('os8', 'os16', 'os32', 'os64', 'os80');
|
{$ifdef debug_OperandSize}
|
||||||
|
OSTEXT: array[TOperandSize] of string = ('os8', 'os16', 'os32', 'os64', 'os48', 'os80', 'os128');
|
||||||
|
{$endif}
|
||||||
var
|
var
|
||||||
BytesRead: Cardinal;
|
|
||||||
S, Soper: String;
|
S, Soper: String;
|
||||||
n: Integer;
|
n: Integer;
|
||||||
HasMem: Boolean;
|
HasMem: Boolean;
|
||||||
begin
|
begin
|
||||||
BytesRead := 0;
|
Code := AAddress;
|
||||||
if not ReadProcessMemory(AProcess, Pointer(Address), @Code, SizeOf(Code), BytesRead) and (BytesRead = SizeOf(Code))
|
|
||||||
then begin
|
|
||||||
Log('Disassemble: Failed to read memory at %s, got %u bytes', [FormatAddress(Address), BytesRead]);
|
|
||||||
ACode := '??';
|
|
||||||
ACodeBytes := '??';
|
|
||||||
Inc(Address);
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Segment := '';
|
Segment := '';
|
||||||
Opcode := '';
|
Opcode := '';
|
||||||
@ -3028,10 +3079,14 @@ begin
|
|||||||
begin
|
begin
|
||||||
if Operand[n].ByteCount = 0
|
if Operand[n].ByteCount = 0
|
||||||
then S := Operand[n].Value
|
then S := Operand[n].Value
|
||||||
else S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags)]);
|
else begin
|
||||||
|
if Operand[n].ByteCount2 = 0
|
||||||
|
then S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags)])
|
||||||
|
else S := Format(Operand[n].Value, [HexValue(Code[CodeIdx], Operand[n].ByteCount, Operand[n].FormatFlags), HexValue(Code[CodeIdx + Operand[n].ByteCount], Operand[n].ByteCount2, Operand[n].FormatFlags)])
|
||||||
|
end;
|
||||||
|
|
||||||
if Soper <> '' then Soper := Soper + ',';
|
if Soper <> '' then Soper := Soper + ',';
|
||||||
if Operand[n].IsMemory
|
if ofMemory in Operand[n].Flags
|
||||||
then begin
|
then begin
|
||||||
if (OperIdx = 1)
|
if (OperIdx = 1)
|
||||||
// or (Operand[n].Size <> os32)
|
// or (Operand[n].Size <> os32)
|
||||||
@ -3042,6 +3097,7 @@ begin
|
|||||||
end
|
end
|
||||||
else Soper := Soper + S;
|
else Soper := Soper + S;
|
||||||
Inc(CodeIdx, Operand[n].ByteCount);
|
Inc(CodeIdx, Operand[n].ByteCount);
|
||||||
|
Inc(CodeIdx, Operand[n].ByteCount2);
|
||||||
end;
|
end;
|
||||||
{$ifdef debug_OperandSize}
|
{$ifdef debug_OperandSize}
|
||||||
Soper := Soper + ' | ';
|
Soper := Soper + ' | ';
|
||||||
@ -3052,9 +3108,9 @@ begin
|
|||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
S := '';
|
S := '';
|
||||||
if preLock in Flags then S := S + '**lock:**';
|
if preLock in Flags then S := S + '**lock**';
|
||||||
if preRep in Flags then S := S + '?rep:?';
|
if preRep in Flags then S := S + '?rep?';
|
||||||
if preRepNE in Flags then S := S + '?repne:?';
|
if preRepNE in Flags then S := S + '?repne?';
|
||||||
S := S + Opcode;
|
S := S + Opcode;
|
||||||
if not HasMem and (Segment <> '') then S := S + ' ?' + Segment + '?';
|
if not HasMem and (Segment <> '') then S := S + ' ?' + Segment + '?';
|
||||||
ACode := S + ' ' + Soper;
|
ACode := S + ' ' + Soper;
|
||||||
@ -3066,7 +3122,7 @@ begin
|
|||||||
S := S + HexStr(Code[n], 2);
|
S := S + HexStr(Code[n], 2);
|
||||||
end;
|
end;
|
||||||
ACodeBytes := S;
|
ACodeBytes := S;
|
||||||
Inc(Address, CodeIdx);
|
Inc(AAddress, CodeIdx);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user