📄 disasm.pas
字号:
else
OperandSize := 2;
// DWord
'd': OperandSize := 4;
// 32 or 48 bit pointer
'p': OperandSize := AddressSize + 2;
// QWord
'q': OperandSize := 8;
// 6Byte
's': OperandSize := 6;
// Word or DWord
'v': OperandSize := DeffOperandSize;
// Word
'w': OperandSize := 2;
// Tera byte
't': OperandSize := 10;
end;
case AddrMethod of
// Direct Address.
'A': if OperandType = 'p' then
begin
// Read address and return it.
if SegOverride then
Result := SegName + ':'
else
Result := '';
if AddressSize = 4 then
Result := Result + GetRefAddress
else
Result := Result + '$' + IntToHex(ReadWord, 2);
end
else
// A direct address the isn't a pointer??
raise EDisAsmError.Create(err_invalid_operand);
// Reg field in ModRm specifies Control register.
'C': if OperandType = 'd' then
begin
// Read Reg part of the ModRM field.
Result := Format('C%d', [(ModRM and modrmReg) div 8]);
MustHaveSize := False;
end
else
// Only support for the complete register.
raise EDisAsmError.Create(err_invalid_operand);
// Reg field in ModRm specifies Debug register.
'D': if OperandType = 'd' then
begin
// Read Reg part of the ModRM field.
Result := Format('D%d', [(ModRM and modrmReg) div 8]);
MustHaveSize := False;
end
else
// Only support for the complete register.
raise EDisAsmError.Create(err_invalid_operand);
// General purpose register or memory address specified in the ModRM byte.
// There are no check for invalid operands.
'E', 'M', 'R': Result := GetEffectiveAddress(False);
// EFlags register
'F': { Do nothing };
// Reg field in ModRM specifies a general register
'G': begin
Result := GetRegName((ModRM and modrmReg) div 8);
MustHaveSize := False;
end;
// Signed immidate data
'H': begin
case OperandSize of
1: I := ShortInt(ReadByte);
2: I := Smallint(ReadWord);
4: I := Integer(ReadDWord);
else raise EDisAsmError.Create(err_invalid_operand_size);
end;
Result := SignedIntToHex(I, OperandSize * 2);
if Assigned(OnImmidiateData) then
OnImmidiateData(Param, Address + Size - OperandSize, OperandSize, True, Result);
Result := '^' + chr(Length(Result)) + Result;
end;
// Imidiate data
'I': begin
Result := '';
for I := OperandSize downto 1 do
Result := IntToHex(ReadByte, 2) + Result;
Result := '$' + Result;
if Assigned(OnImmidiateData) then
OnImmidiateData(Param, Address + Size - OperandSize,
OperandSize, False, Result);
Result := '^' + Chr(Length(Result)) + Result;
end;
// Relative jump Offset Byte
'J': begin
case OperandSize of
1: I := ShortInt(ReadByte);
2: I := Smallint(ReadWord);
4: I := Integer(ReadDWord);
else raise EDisAsmError.Create(err_invalid_operand_size);
end;
// Convert the value to a string.
Result := SignedIntToHex(I, OperandSize * 2);
// if its a jump call the JumpInstr proc.
if (EnhOperandType = 'j') and Assigned(OnJumpInstr) then
begin
OnJumpInstr(Param, Address + Size - OperandSize, Address + Size + I, Result);
Result := '^' + Chr(Length(Result)) + Result;
end;
if (EnhOperandType = 'c') and Assigned(OnCallInstr) then
begin
OnCallInstr(Param, Address + Size - OperandSize, Address + Size + I, Result);
Result := '^' + Chr(Length(Result)) + Result;
end;
end;
// Relative Offset Word or DWord
'O': if AddressSize = 2 then
Result := '%s' + Chr(OperandSize) + '[$' + IntToHex(ReadWord, 4) + ']'
else
begin
Result := '%s' + Chr(OperandSize) + '[' + GetRefAddress + ']';
if Assigned(OnRef) then
OnRef(Param, Ref, OperandSize, Result);
end;
// Reg field in ModRM specifies a MMX register
'P': begin
Result := Format('MM%d', [(ModRM and modrmReg) div 8]);
MustHaveSize := False;
end;
// MMX register or memory address specified in the ModRM byte.
'Q': if (ModRM and modrmmod) = $C0 then
begin
// MMX register
Result := Format('MM%d', [(ModRM and modrmReg) div 8]);
MustHaveSize := False;
end
else
// Effective address
Result := GetEffectiveAddress(False);
// Reg field in ModRM specifies a Segment register
'S': case (ModRM and modrmReg) div 8 of
0: Result := 'es';
1: Result := 'cs';
2: Result := 'ss';
3: Result := 'ds';
4: Result := 'fs';
5: Result := 'gs';
end;
// Reg field in ModRM specifies a MMX register
'T': begin
Result := Format('T%d', [(ModRM and modrmReg) div 8]);
MustHaveSize := False;
end;
end;
end;
function Replacer(FirstChar, SecondChar: char): string;
const
modrmReg = $38; // Reg part of the ModRM byte, ??XXX???
begin
case FirstChar of
// escape character
'c': if SecondChar = '2' then
Result := TwoByteOpcodes[char(ReadByte)]
else
if ModRm <= $BF then
Result := FloatingPointOpcodes[SecondChar, (ModRM and modrmReg) div 8 + $B8]
else
Result := FloatingPointOpcodes[SecondChar, ModRm];
// 32 bit register or 16 bit register.
'e': if DeffOperandSize = 4 then
Result := 'e' + SecondChar
else
Result := SecondChar;
// Seg prefix override.
'p': begin
SegOverride := True;
SegName := SecondChar + 's';
Result := OneByteOpcodes[char(ReadByte)];
end;
// Size override (address or operand).
's': begin
case SecondChar of
'o': DeffOperandSize := 2;
'a': AddressSize := 2;
end;
Result := OneByteOpcodes[char(ReadByte)];
end;
// Operand size
'o': if DeffOperandSize = 4 then
case SecondChar of
'2': Result := 'w';
'4': Result := 'd';
'8': Result := 'q';
end
else
case SecondChar of
'2': Result := 'b';
'4': Result := 'w';
'8': Result := 'd';
end;
// Must have size.
'm': begin
Result := '';
MustHaveSize := True;
end;
// Group, return the group insruction specified by OperandType
// and the reg field of the ModRM byte.
'g': Result := GroupsOpcodes[SecondChar, (ModRM and modrmReg) div 8];
// Operand for group, return operands for the group insruction specified
// by OperandType and the reg field of the ModRM byte.
'h': Result := GroupsOperands[SecondChar, (ModRM and modrmReg) div 8];
end;
end;
var
I, J, ps1, ps2, k : Integer;
begin
DeffOperandSize := 4;
AddressSize := 4;
SegOverride := False;
Size := 0;
XHasSib := False;
XHasModRM := False;
MustHaveSize := True;
Ref.MultiplyReg1 := 0;
Ref.MultiplyReg2 := 0;
Ref.Immidiate := nil;
Result := OneByteOpcodes[char(ReadByte)];
I := 1;
while I < Length(Result) -1 do
case Result[I] of
'#': begin
Insert(Operand(Result[I+1], Result[I+2], Result[I+3]), Result, I + 4);
Delete(Result, I, 4);
end;
'@': begin
Insert(Replacer(Result[I+1], Result[I+2]), Result, I + 3);
Delete(Result, I, 3);
end;
'^': begin
// Skip the numbers of character indicate in the next char.
J := I;
Inc(I, Ord(Result[I+1]));
Delete(Result, J, 2);
end;
else Inc(I);
end;
// Replace '%s' with size name if MustHaveSize = true or nothing.
I := 1;
while I < Length(Result) -1 do
case Result[I] of
'%': begin
case Result[I+1] of
's': if MustHaveSize then
case Result[I+2] of
#1: Insert('byte ptr ', Result, I + 3);
#2: Insert('word ptr ', Result, I + 3);
#4: Insert('dword ptr ', Result, I + 3);
#6: ;
#8: Insert('qword ptr ', Result, I + 3);
#10: Insert('tbyte ptr ', Result, I + 3);
else
//raise Exception.CreateFmt('Size out of range. %d', [Ord(Result[I+2])]);
//MessageBox(0,PChar('Not fatal error occured. '+#13#10+'Size out of range'+#13#10+'Convertion will continue ...'),PChar('OPCODE Engine Error'),0);
Insert('???? ptr ', Result, I + 3);
end;
'c': begin
// Include the opcode as DB.
Insert(' //', Result, I + 3);
for J := Size -1 downto 1 do
Insert(', $' + IntToHex(PByte(Address + J)^, 2), Result, I + 3);
Insert('DB $' + IntToHex(PByte(Address)^, 2), Result, I + 3);
end;
end;
Delete(Result, I, 3);
end;
else Inc(I);
end;
//////////////////////////////////////////////////////////////////////
//Added by DaFixer - Fix the addresses to always be 8 chars in lenth
//
ps1:=Pos('[$',Result);
if ps1<>0 then
begin
ps2:=Pos(']',Result);
if ps2-ps1<10 then
for k:=ps2-ps1 to 9 do Insert('0',Result,ps1+2);
end;
//
///////////////////////////////////////////////////////////////////////
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, 1);
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, 1);
end;
Result := nil;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -