Ярослав, зроблю конкретно і чітко — шматки коду + де саме їх вставити. Без зайвої теорії.
Проблема у тебе в групових інструкціях, де src — це opcode extension.
Там обов'язково треба ловити недопустимі значення.
---
1️⃣ Виправлення для $83 (Grp83)
Знайди у коді:
{ $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;
5: begin v := GetRM - imm; SetRM(v); SetFlags(v); end;
7: begin v := GetRM - imm; SetFlags(v); end;
end;
inc(eip,3);
end;
---
Замінити на:
{ $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;
---
2️⃣ Виправлення для $F7
У тебе зараз:
Optable[$F7] := opMUL;
Це неправильно, бо $F7 — це група інструкцій.
---
Крок 1
Знайди:
{ $F7}
procedure opMUL;
var v:Int64;
begin
DecodeModRM;
v := Int64(eax) * Int64(GetRM);
eax := DWord(v);
edx := DWord(v shr 32);
NextRM;
end;
---
Крок 2
Заміни на групу F7
{ $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;
---
Крок 3
У InitCPU знайди:
Optable[$F7] := opMUL;
Замінити на:
Optable[$F7] := opGrpF7;
---
3️⃣ Маленьке виправлення у p0F
Знайди:
procedure p0F;
begin
case RAM[eip+1] of
$84: opJZ_rel32;
$85: opJNZ_rel32;
$88: opJS_rel32;
else
ErrorOpCode(2);
end;
end;
---
Краще зробити так:
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;
---
4️⃣ Маленьке виправлення у $FF
У тебе вже майже правильно.
Тільки додай exit.
Знайди:
else ErrorOpCode(2);
замінити на:
else
begin
ErrorOpCode(2);
exit;
end;
---
5️⃣ Підсумок (де саме ти ловиш помилки)
місце перевірка
opcode ErrorOpCode(1)
0F opcode ErrorOpCode(2)
66 opcode ErrorOpCode(2)
83 /digit ErrorOpCode(2)
F7 /digit ErrorOpCode(2)
FF /digit ErrorOpCode(2)
---
6️⃣ Найважливіше
Ти питав:
> "чи можливі недопустимі значення в DecodeModRM"
Відповідь:
❌ ні
modrm — це звичайний байт, тому:
mod = 0..3
reg = 0..7
rm = 0..7
Це завжди допустимі значення.
Помилки можуть бути тільки у групових opcode.
---
✅ Якщо хочеш, я можу ще показати одну реально небезпечну помилку, яка у тебе є зараз — вона може іноді зламати CALL / JMP через NextRM.
Вона маленька, але дуже підступна.
