📄 emulator.pas
字号:
unit Emulator;
interface
uses FatExpression, Classes;
const
MaxStack = 10000;
type DWORD = Longword;
type TCPUEmulator = class(TComponent)
Calc: TFatExpression;
procedure CalcEvaluate(Sender: TObject; Eval: String;
Args: array of Double; ArgCount: Integer; var Value: Double;
var Done: Boolean);
private
Regs : array[1..8] of dword;
Stack : array[0..MaxStack] of dword;
FPUStack : array[0..10] of Extended;
OpSize : byte;
Command : string;
OpCount : integer;
Ops : array[1..4] of string;
function RegNum(const regname : string) : integer;
function RegSize(const regname : string) : integer;
function OpType(const s : string) : integer;
function StripBrackets (const s : string) : string;
function GetOperand(const expr : string) : dword;
procedure SetOperand(const expr : string; const Value : dword);
procedure SetOpSize(const Cmd : string);
procedure ExpandCommand(const Cmd : string);
function HexToInt(const s : string) : string;
procedure SetByte(const b : byte);
procedure SetWord(const w : word);
procedure SetDWord(const d: dword);
public
constructor Create;
destructor Destroy; override;
function GetRegValue(const regname : string) : dword;
procedure SetRegValue(const regname : string; const value : dword);
procedure Emulate(const Cmd : string);
end; {TCPUEmulator}
implementation
Uses MainUnit, SysUtils, HexTools;
constructor TCPUEmulator.Create;
begin
Calc := TFatExpression.Create(Self);
{
Calc.Functions.Add('eax');
Calc.Functions.Add('ebx');
Calc.Functions.Add('ecx');
Calc.Functions.Add('edx');
Calc.Functions.Add('edi');
Calc.Functions.Add('esi');
Calc.Functions.Add('ebp');
Calc.Functions.Add('esp');
Calc.Functions.Add('ax');
Calc.Functions.Add('bx');
Calc.Functions.Add('cx');
Calc.Functions.Add('dx');
Calc.Functions.Add('ah');
Calc.Functions.Add('bh');
Calc.Functions.Add('ch');
Calc.Functions.Add('dh');
Calc.Functions.Add('al');
Calc.Functions.Add('bl');
Calc.Functions.Add('cl');
Calc.Functions.Add('dl');
}
Calc.EvaluateOrder := eoEventFirst;
Calc.OnEvaluate := CalcEvaluate;
end;
destructor TCPUEmulator.Destroy;
begin
Calc.Destroy;
end;
procedure TCPUEmulator.SetByte(const b : byte);
begin
end;
procedure TCPUEmulator.SetWord(const w : word);
begin
end;
procedure TCPUEmulator.SetDWord(const d: dword);
begin
end;
function TCPUEmulator.HexToInt(const s : string) : string;
var
i : integer;
j : integer;
begin
i := Pos('$', s);
if i > 0 then begin
j := i + 1;
while Pos(s[j], '0123456789ABCDEF') > 0 do begin
inc(j);
end; { while }
Result := Copy(s, 1, i - 1) + IntToStr(StrToInt64(Copy(s, i, j-i))) + Copy(s, j+1, Length(s) - j);
end else begin
Result := s;
end;
end;
function TCPUEmulator.OpType(const s : string) : integer;
begin
if Pos('[', s) > 0 then begin
if Pos('ebp', s) > 0 then begin
Result := 2;
end else begin
Result := 1;
end; { if }
end else begin
Result := 0;
end; { if }
end;
function TCPUEmulator.StripBrackets (const s : string) : string;
var
i, j : integer;
begin
i := Pos('[', s) + 1;
j := Pos(']', s);
if (j > 0) then
Result := Copy(s, i, j - i)
else
Result := s;
end;
function TCPUEmulator.RegSize(const regname : string) : integer;
begin
if pos('e', regname) > 0 then
Result := 4
else if (pos('h', regname) > 0) then
Result := 3
else if (pos('l', regname) > 0) then
Result := 1
else
Result := 2;
end;
function TCPUEmulator.RegNum(const regname : string) : integer;
const
regs4 = ' eaxebxecxedxediesiebpesp';
regs2 = ' ahalbhblchcldhdl';
var
i : integer;
begin
i := Pos(regname, regs2) div 4;
if i < 1 then begin
i := Pos(regname, regs4) div 3;
end; { if }
Result := i;
end;
function TCPUEmulator.GetRegValue(const regname : string) : dword;
var
i : integer;
begin
i := RegNum(regname);
case RegSize(regname) of
1 : Result := Regs[i] and $FF;
2 : Result := Regs[i] and $FFFF;
3 : Result := (Regs[i] and $FF00) SHR 8;
4 : Result := Regs[i];
end; { case }
end;
procedure TCPUEmulator.SetRegValue(const regname : string; const value : dword);
var
i : integer;
begin
i := RegNum(regname);
case RegSize(regname) of
1 : Regs[i] := (Regs[i] and $FFFFFF00) OR (Value AND $FF);
2 : Regs[i] := (Regs[i] and $FFFF0000) OR (Value AND $FFFF);
3 : Regs[i] := (Regs[i] and $FFFF00FF) OR ((Value AND $FF00)SHL 8);
4 : Regs[i] := Value;
end; { case }
end;
procedure TCPUEmulator.CalcEvaluate(Sender: TObject; Eval: String;
Args: array of Double; ArgCount: Integer; var Value: Double;
var Done: Boolean);
begin
Value := GetRegValue(Eval);
Done := true;
end;
function TCPUEmulator.GetOperand(const expr : string) : dword;
var
i : dword;
begin
Calc.Text := StripBrackets(expr);
i := StrToInt64(FloatToStr(Calc.Value));
case OpType(expr) of
0 : Result := i;
1 : begin
case OpSize of
1 : Result := GetByte(i);
2 : Result := GetWord(i);
4 : Result := GetDWord(i);
end; { case }
end;
2 : begin
end;
end; { case }
end;
procedure TCPUEmulator.SetOperand(const expr : string; const Value : dword);
begin
case OpType(expr) of
0 : if RegNum(expr) > 0 then begin
SetRegValue(expr, Value);
end;
1 : begin
{ case OpSize of
1 : Result := SetByte(i);
2 : Result := SetWord(i);
4 : Result := SetDWord(i);
end; { case }
end;
2 : begin
end;
end; { case }
end;
procedure TCPUEmulator.SetOpSize(const Cmd : string);
begin
if Pos('dword', cmd) > 0 then OpSize := 4
else if Pos('word', cmd) > 0 then OpSize := 2
else if Pos('byte', cmd) > 0 then OpSize := 1
else OpSize := 4;
end;
procedure TCPUEmulator.ExpandCommand(const Cmd : string);
var
i, j : integer;
s : string;
begin
s := LowerCase(Trim(Cmd));
i := Pos(' ', s);
OpCount := 0;
if i > 0 then begin
Command := Trim(Copy(s, 1, i));
Delete(s, 1, i);
while true do begin
i := Pos(',', s);
inc(OpCount);
if i < 1 then begin
Ops[OpCount] := HexToInt(Trim(s));
break;
end else begin
Ops[OpCount] := HexToInt(Trim(Copy(s, 1, i - 1)));
Delete(s, 1, i);
end; { if }
end; { while }
end else begin
Command := s;
end; { if }
for i:= 1 to OpCount do begin
j := Pos('ptr', Ops[i]);
if j > 0 then Ops[i] := Trim(Copy(Ops[i], j+3, Length(Ops[i])-(j+2)));
end; { for }
end;
procedure TCPUEmulator.Emulate(const Cmd : string);
begin
SetOpSize(Cmd);
ExpandCommand(Cmd);
if Command = 'mov' then begin
SetOperand(Ops[1], GetOperand(Ops[2]));
end else if Command = 'add' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) + GetOperand(Ops[2]));
end else if Command = 'sub' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) - GetOperand(Ops[2]));
end else if Command = 'inc' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) + 1);
end else if Command = 'dec' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) - 1);
end else if Command = 'lea' then begin
SetOperand(Ops[1], GetOperand(StripBrackets(Ops[2])));
end else if Command ='and' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) AND GetOperand(Ops[2]));
end else if Command ='or' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) OR GetOperand(Ops[2]));
end else if Command ='xor' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) XOR GetOperand(Ops[2]));
end else if Command ='not' then begin
SetOperand(Ops[1], NOT GetOperand(Ops[1]));
end else if Command ='neg' then begin
SetOperand(Ops[1], - GetOperand(Ops[1]));
end else if Command ='shl' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) SHL GetOperand(Ops[2]));
end else if Command ='shr' then begin
SetOperand(Ops[1], GetOperand(Ops[1]) SHR GetOperand(Ops[2]));
end; { if }
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -