{ChatGPT:
1. Дякую за все! 
2. Переробив DecodeModRM для "помилок". ану глянь, будь ласка
}
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] 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 ErrorOpCode1;
begin OpcodeERRValue:=1;{помилка в першому байті}
If TrapInvalidOpcode=1{обробка прог.користувача} then begin OpcodeERRHasOperatedMistake;
Dec(esp,4); WriteDWord(esp,eip); eip := InvalidOpcodeVector; end else
begin
ShowMessage('OpcodeERRValue:= '+Inttostr(OpcodeERRValue));
end;
end;
procedure ErrorOpCode2;
begin OpcodeERRValue:=2;{помилка в другому байті}
If TrapInvalidOpcode=1{обробка прог.користувача} then begin OpcodeERRHasOperatedMistake;
Dec(esp,4); WriteDWord(esp,eip); eip := InvalidOpcodeVector; end else
begin
ShowMessage('OpcodeERRValue:= '+Inttostr(OpcodeERRValue));
end;
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 =================}
Function DecodeModRM:boolean;var m:Byte; begin DecodeModRM:=true;modrm := RAM[eip+1]; src := (modrm shr 3) and 7; dst := modrm and 7; m := modrm shr 6; 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));
else begin DecodeModRM:=False;{помилка}end;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;
{================ FLAGS =================}
procedure SetFlags(v:DWord);begin pZF := v=0; pSF := (v and $80000000)<>0; end;
{================ ALU =================}
{ $01}procedure opADD;var v:DWord;begin If DecodeModRM then begin v := GetRM + Reg[src];SetRM(v);SetFlags(v);NextRM;end else ErrorOpCode2;end;
{ $09}procedure opOR;var v:DWord;begin If DecodeModRM then begin v := GetRM or Reg[src];SetRM(v);SetFlags(v);NextRM;end else ErrorOpCode2;end;
{ $21}procedure opAND;var v:DWord;begin If DecodeModRM then begin v := GetRM and Reg[src];SetRM(v);SetFlags(v);NextRM;end else ErrorOpCode2;end;
{ $29}procedure opSUB;var v:DWord;begin If DecodeModRM then begin v := GetRM - Reg[src];SetRM(v);SetFlags(v);NextRM;end else ErrorOpCode2;end;
{ $31}procedure opXOR;var v:DWord;begin If DecodeModRM then begin v := GetRM xor Reg[src];SetRM(v);SetFlags(v);NextRM; end else ErrorOpCode2;end;
{ $39}procedure opCMP;var v:DWord;begin If DecodeModRM then begin v := GetRM - Reg[src];SetFlags(v);NextRM;end else ErrorOpCode2;end;
{=========== ADD/SUB/CMP imm8 ============}
{ $83}procedure opGrp83;var imm:ShortInt; v:DWord;begin If DecodeModRM then begin imm := ShortInt(RAM[eip+2]);case src of 0: begin v := GetRM + imm; SetRM(v); SetFlags(v); end; 5: begin v := GetRM - imm; SetRM(v); SetFlags(v); end; 7: begin v := GetRM - imm; SetFlags(v); end;end;inc(eip,3);end else ErrorOpCode2;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 If DecodeModRM then begin v := Byte(Reg[src]);if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFFFF00) or v else WriteByte(addr,v);NextRM;end else ErrorOpCode2;end;
{ $89}procedure opMOV_rm_r;begin If DecodeModRM then begin SetRM(Reg[src]);NextRM;end else ErrorOpCode2;end;
{ $8A }procedure opMOV_r8_rm8;var v:Byte;begin If DecodeModRM then begin if (modrm shr 6)=3 then v := Byte(Reg[dst])else v := ReadByte(addr);Reg[src] := (Reg[src] and $FFFFFF00) or v;NextRM;end else ErrorOpCode2;end;
{ $8B}procedure opMOV_r_rm;begin If DecodeModRM then begin Reg[src] := GetRM;NextRM;end else ErrorOpCode2;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 If DecodeModRM then begin 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 else ErrorOpCode2;end;
{ $C7} procedure opMOV_rm32_imm32;var v:DWord;begin If DecodeModRM then begin v := ReadDWord(eip+2);SetRM(v);inc(eip,6);end else ErrorOpCode2;end;
{ $66 $89}procedure opMOV_rm16_r16;var v:Word;begin If DecodeModRM then begin v := Word(Reg[src]);if (modrm shr 6)=3 then Reg[dst] := (Reg[dst] and $FFFF0000) or v else WriteWord(addr,v);NextRM;end else ErrorOpCode2;end;
{ $66 $8B}procedure opMOV_r16_rm16;var v:Word;begin If DecodeModRM then begin if (modrm shr 6)=3 then v := Word(Reg[dst])else v := ReadWord(addr);Reg[src] := (Reg[src] and $FFFF0000) or v;NextRM;end else ErrorOpCode2;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 If DecodeModRM then begin 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 else ErrorOpCode2;end;
{================ MUL =================}
{ $F7}procedure opMUL;var v:Int64;begin If DecodeModRM then begin v := Int64(eax) * Int64(GetRM);eax := DWord(v);edx := DWord(v shr 32);NextRM;end else ErrorOpCode2;end;
{ $AF}procedure opIMUL;var v:Int64;begin If DecodeModRM then begin v := Int64(Integer(eax)) * Int64(Integer(GetRM));eax := DWord(v);edx := DWord(v shr 32);NextRM;end else ErrorOpCode2;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 ErrorOpCode2;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 ErrorOpCode2;end;end;
{ $FF}procedure pFF; var v:DWord; begin If DecodeModRM then begin
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 ErrorOpCode2;end;end else ErrorOpCode2;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] := opMUL; {спрощено}
Optable[$0F] := p0F;
Optable[$66] := p66;
Optable[$FF] := pFF;
TrapInvalidOpcode:=0;
TrapInvalidINT:=0;
end;
procedure ENGINE;{================ ENGINE =================}
var opcode:DWord;
begin
vAPM:=0; repeat
opcode := RAM[eip];
Optable[opcode]();
until vAPM<>0;
//if (vProgramHalt=0) and (OpcodeERRValue=$FFFFFFFF) then ErrorOpCode2;
end;
end.
;mov byte [1000],5
;mov al,[1000]
;mov byte [1001],10
;mov al,[1001]
;mov byte [eax],1
mov word [1000],1234
mov ax,[1000]
mov ax,1234