{ChatGPT:Писати тобі буду знизу після коду так зручніше, добре ?! і мітку якось для себе буду ставити повідомленню}
unit uASM32;
interface
uses uSysVar;
type DWord = Cardinal;
var eax,ecx,edx,ebx,esp,ebp,esi,edi,eip:DWord;Reg:array[0..7] of DWord absolute eax;
RAM:array[0..cSizeOfRAM-1] of Byte;
procedure LoadBIN(const FileName:string; LoadAddr:DWord);
procedure WriteDWord(a,v:DWord);
procedure InitCPU;
procedure ENGINE;
implementation
uses Dialogs,SysUtils,uINT40;
var pZF,pCF,pSF,pOF:Boolean;
type TOpcode = procedure();
var Optable:array[0..255] of TOpcode;
modrm,src,dst,addr:DWord;
procedure LoadBIN(const FileName:string; LoadAddr:DWord);
var f:file; size,i:DWord; b:Byte;
begin
Assign(f,FileName); Reset(f,1); size := FileSize(f);
for i:=0 to size-1 do
begin BlockRead(f,b,1); RAM[LoadAddr+i] := b; end; Close(f);
eip := LoadAddr; {початок виконання}
end;
procedure OpcodeERRHasOperatedMistake; {якщо зпрацювала помилка опкоду}
begin OpcodeERReax:=eax; OpcodeERRecx:=ecx; OpcodeERRedx:=edx; OpcodeERRebx:=ebx;
OpcodeERResp:=esp; OpcodeERRebp:=ebp; OpcodeERResi:=esi; OpcodeERRedi:=edi;
OpcodeERReip:=eip; OpcodeERRRAMeip:=RAM[eip]
end;
procedure ErrorOpCode(v:DWord);
begin
OpcodeERRValue := v;
if TrapInvalidOpcode=1 then
begin
OpcodeERRHasOperatedMistake;
Dec(esp,4);
WriteDWord(esp,eip);
eip := InvalidOpcodeVector;
end
else begin ShowMessage('OpcodeERRValue='+IntToStr(v)); Halt; end;
end;
procedure ErrorOpCode1;
begin
ErrorOpCode(1);
end;
{================ MEMORY =================}
function ReadByte(a:DWord):Byte; begin Result := RAM[a];end;
procedure WriteByte(a:DWord; v:Byte); begin RAM[a] := v;end;
procedure WriteWord(a:DWord; v:Word);begin RAM[a] := Byte(v); RAM[a+1] := Byte(v shr 8);end;
function ReadDWord(a:DWord):DWord; begin Result := DWord(RAM[a]) or (DWord(RAM[a+1]) shl 8) or (DWord(RAM[a+2]) shl 16) or (DWord(RAM[a+3]) shl 24);end;
function ReadWord(a:DWord):Word; begin Result := RAM[a] or (RAM[a+1] shl 8);end;
procedure WriteDWord(a,v:DWord);begin RAM[a] := Byte(v);RAM[a+1] := Byte(v shr 8);RAM[a+2] := Byte(v shr 16);RAM[a+3] := Byte(v shr 24);end;
{================ MODRM =================}
procedure DecodeModRM;var m:Byte; begin modrm := RAM[eip+1]; m := (modrm shr 6) and 3; src := (modrm shr 3) and 7; dst := modrm and 7; if m=3 then addr := 0 else begin case m of 0: addr := Reg[dst]; 1: addr := Reg[dst] + ShortInt(RAM[eip+2]); 2: addr := Reg[dst] + Integer(ReadDWord(eip+2));end;end;end;
function GetRM:DWord; begin if (modrm shr 6)=3 then Result := Reg[dst]else Result := ReadDWord(addr);end;
procedure SetRM(v:DWord);begin if (modrm shr 6)=3 then Reg[dst] := v else WriteDWord(addr,v);end;
procedure NextRM;begin case modrm shr 6 of 0: inc(eip,2); 1: inc(eip,3); 2: inc(eip,6); 3: inc(eip,2);end;end;
procedure NextRMImm8; begin NextRM; inc(eip); end;
procedure NextRMImm32; begin NextRM; inc(eip,4); end;
{================ FLAGS =================}
procedure SetFlags(v:DWord);begin pZF := v=0; pSF := (v and $80000000)<>0; end;
{================ ALU =================}
{ $01}procedure opADD;var v:DWord;begin DecodeModRM;v := GetRM + Reg[src];SetRM(v);SetFlags(v);NextRM;end;
{ $09}procedure opOR;var v:DWord;begin DecodeModRM;v := GetRM or Reg[src];SetRM(v);SetFlags(v);NextRM;end;
{ $21}procedure opAND;var v:DWord;begin DecodeModRM;v := GetRM and Reg[src];SetRM(v);SetFlags(v);NextRM;end;
{ $29}procedure opSUB;var v:DWord;begin DecodeModRM;v := GetRM - Reg[src];SetRM(v);SetFlags(v);NextRM;end;
{ $31}procedure opXOR;var v:DWord;begin DecodeModRM;v := GetRM xor Reg[src];SetRM(v);SetFlags(v);NextRM;end;
{ $39}procedure opCMP;var v:DWord;begin DecodeModRM;v := GetRM - Reg[src];SetFlags(v);NextRM;end;
{=========== ADD/SUB/CMP imm8 ============}
{ $83}
procedure opGrp83;
var imm:ShortInt; v:DWord;
begin
DecodeModRM;
imm := ShortInt(RAM[eip+2]);
case src of
0: begin v := GetRM + imm; SetRM(v); SetFlags(v); end; {ADD}
5: begin v := GetRM - imm; SetRM(v); SetFlags(v); end; {SUB}
7: begin v := GetRM - imm; SetFlags(v); end; {CMP}
else
begin
ErrorOpCode(2);
exit;
end;
end;
inc(eip,3);
end;
{================ INC/DEC =================}
{ $40 to $47}procedure opINC;begin dst := RAM[eip] and 7;Inc(Reg[dst]);SetFlags(Reg[dst]);inc(eip);end;
{ $48 to $4F}procedure opDEC;begin dst := RAM[eip] and 7;Dec(Reg[dst]);SetFlags(Reg[dst]);inc(eip);end;
{================ STACK =================}
{ $50 to $57}procedure opPUSH_r32;begin dst := RAM[eip] and 7;Dec(esp,4);WriteDWord(esp,Reg[dst]);inc(eip);end;
{ $58 to $5F}procedure opPOP_r32;begin dst := RAM[eip] and 7;Reg[dst] := ReadDWord(esp);Inc(esp,4);inc(eip);end;
{================ MOV =================}
{ $88 } procedure opMOV_rm8_r8;var v:Byte;begin DecodeModRM;v := Byte(Reg[src]);if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFFFF00) or v else WriteByte(addr,v);NextRM;end;
{ $89}procedure opMOV_rm_r;begin DecodeModRM;SetRM(Reg[src]);NextRM;end;
{ $8A }procedure opMOV_r8_rm8;var v:Byte;begin DecodeModRM;if (modrm shr 6)=3 then v := Byte(Reg[dst])else v := ReadByte(addr);Reg[src] := (Reg[src] and $FFFFFF00) or v;NextRM;end;
{ $8B}procedure opMOV_r_rm;begin DecodeModRM;Reg[src] := GetRM;NextRM;end;
{ $B8 to $BF}procedure opMOV_r32_imm;begin dst := RAM[eip] and 7;Reg[dst] := ReadDWord(eip+1);inc(eip,5);end;
{ $C6}procedure opMOV_rm8_imm8; var v:Byte;begin DecodeModRM;v := RAM[eip+2];if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFFFF00) or v else WriteByte(addr,v);inc(eip,3);end;
{ $C7} procedure opMOV_rm32_imm32;var v:DWord;begin DecodeModRM;v := ReadDWord(eip+2);SetRM(v);inc(eip,6);end;
{ $66 $89}procedure opMOV_rm16_r16;var v:Word;begin DecodeModRM;v := Word(Reg[src]);if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFF0000) or v else WriteWord(addr,v);NextRM;end;
{ $66 $8B}procedure opMOV_r16_rm16;var v:Word;begin DecodeModRM;if (modrm shr 6)=3 then v := Word(Reg[dst])else v := ReadWord(addr);Reg[src] := (Reg[src] and $FFFF0000) or v;NextRM;end;
{ $66 $B8..$BF}procedure opMOV_r16_imm16;begin dst := RAM[eip] and 7;Reg[dst] := (Reg[dst] and $FFFF0000) or ReadWord(eip+1);inc(eip,3);end;
{ $66 $C7}procedure opMOV_rm16_imm16;var v:Word;begin DecodeModRM;v := ReadWord(eip+2);if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFF0000) or v else WriteWord(addr,v);inc(eip,4);end;
{================ MUL =================}
{ $F7}
procedure opGrpF7;
var v:Int64;
begin
DecodeModRM;
case src of
4: begin {MUL}
v := Int64(eax) * Int64(GetRM);
eax := DWord(v);
edx := DWord(v shr 32);
end;
5: begin {IMUL}
v := Int64(Integer(eax)) * Int64(Integer(GetRM));
eax := DWord(v);
edx := DWord(v shr 32);
end;
else
begin
ErrorOpCode(2);
exit;
end;
end;
NextRM;
end;
{ $AF}procedure opIMUL;var v:Int64;begin DecodeModRM; v := Int64(Integer(eax)) * Int64(Integer(GetRM));eax := DWord(v);edx := DWord(v shr 32);NextRM;end;
{================ CONTROL =================}
{ $EB}procedure opJMP_rel08; begin inc(eip, ShortInt(RAM[eip+1]) + 2);end;
{ $66 $E9}procedure opJMP_rel16; begin eip := eip + 3 + SmallInt(ReadWord(eip+1));end;
{ $E9}procedure opJMP_rel32;begin eip := eip + 5 + Integer(ReadDWord(eip+1));end;
{ $66 $E8}procedure opCALL_rel16; begin Dec(esp,4); WriteDWord(esp,eip+3); eip := eip + 3 + SmallInt(ReadWord(eip+1)); end;
{ $E8}procedure opCALL_rel32; begin Dec(esp,4); WriteDWord(esp,eip+5); eip := eip + 5 + Integer(ReadDWord(eip+1)); end;
{ $C3}procedure opRET;begin eip := ReadDWord(esp);Inc(esp,4);end;
{ $74}procedure opJZ;begin if pZF then inc(eip,ShortInt(RAM[eip+1])+2) else inc(eip,2);end;
{ $0F $84}procedure opJZ_rel32; begin if pZF then eip := eip + 6 + Integer(ReadDWord(eip+2)) else inc(eip,6); end;
{ $75}procedure opJNZ;begin if not pZF then inc(eip,ShortInt(RAM[eip+1])+2)else inc(eip,2);end;
{ $0F $85}procedure opJNZ_rel32; begin if not pZF then eip := eip + 6 + Integer(ReadDWord(eip+2)) else inc(eip,6); end;
{ $78}procedure opJS;begin if pSF then inc(eip,ShortInt(RAM[eip+1])+2)else inc(eip,2);end;
{ $0F $88}procedure opJS_rel32; begin if pSF then eip := eip + 6 + Integer(ReadDWord(eip+2)) else inc(eip,6); end;
{================ INT =================}
{ $90}procedure opNOP;begin inc(eip);end;
{ $0F }
procedure p0F;
begin
case RAM[eip+1] of
$84: opJZ_rel32;
$85: opJNZ_rel32;
$88: opJS_rel32;
else
begin
ErrorOpCode(2);
exit;
end;
end;
end;
{ $66}procedure p66;begin inc(eip);case RAM[eip] of $89: opMOV_rm16_r16; $8B: opMOV_r16_rm16; $C7: opMOV_rm16_imm16; $B8..$BF: opMOV_r16_imm16; $E9: opJMP_rel16; $E8: opCALL_rel16;
else begin ErrorOpCode(2); exit; end;end;end;
{ $FF}procedure pFF; var v:DWord; begin DecodeModRM;
case src of
{ }2: begin {CALL r/m32} v := GetRM; Dec(esp,4); WriteDWord(esp,eip+2); eip := v; end;
{ }4: begin {JMP r/m32} eip := GetRM; end;
else begin ErrorOpCode(2); exit; end;end;end;
{================ INIT =================}
procedure InitCPU; var i:Integer; begin
for i:=0 to 255 do Optable[i] := ErrorOpCode1; OpcodeERRValue:=0;
Optable[$01] := opADD; Optable[$09] := opOR; Optable[$21] := opAND; Optable[$29] := opSUB;
Optable[$31] := opXOR; Optable[$39] := opCMP;
for i:=$40 to $47 do Optable[i] := opINC; for i:=$48 to $4F do Optable[i] := opDEC;
for i:=$50 to $57 do Optable[i] := opPUSH_r32; for i:=$58 to $5F do Optable[i] := opPOP_r32;
Optable[$74] := opJZ;Optable[$75] := opJNZ;Optable[$78] := opJS;
Optable[$83] := opGrp83;Optable[$88] := opMOV_rm8_r8;
Optable[$89] := opMOV_rm_r; Optable[$8A] := opMOV_r8_rm8;Optable[$8B] := opMOV_r_rm;
Optable[$90] :=opNOP;
Optable[$AF] := opIMUL;
for i:=$B8 to $BF do Optable[i] := opMOV_r32_imm;
Optable[$C3] := opRET; Optable[$C6] := opMOV_rm8_imm8;Optable[$C7] := opMOV_rm32_imm32;
Optable[$CD] := opINT;
Optable[$E8] := opCALL_rel32; Optable[$E9] := opJMP_rel32; Optable[$EB] := opJMP_rel08;
Optable[$F7] := opGrpF7; {спрощено}
Optable[$0F] := p0F;
Optable[$66] := p66;
Optable[$FF] := pFF;
TrapInvalidOpcode:=0;
TrapInvalidINT:=0;
end;
procedure ENGINE;{================ ENGINE =================}
begin vAPM:=0; repeat Optable[RAM[eip]](); until vAPM<>0; end;
end.
{ChatGPT:
1.Перевірь, наче все вже
}
{для себе: 1034}