Рассказываю.
Разбирался с аппаратной визуализацией.
Сложного нет, но есть куча нюансов. Поэтому от аппаратно VM86 отказался в пользу программного, пол ядра под него переписать надо. Программная эмуляция у меня почти всех 286 команд.
Приведу код. Давно разбирался так как что к чему не помню.
Включить VM86 просто это установить нужный флаг. Просто так установить флаг этот нельзя. Один если не единственный способ это сделать используя iretd.
Далее пошли нюансы
Надо установить флаг NT в 0. Какое-то ограничение с обработкой исключений, это тоже обязательное.
and Word [esp], not 4000h //Сбрасываем NT флаг В 0
and Word [esp], not 3000h //Устанавливаем IOPL В 0
Для обработки портов есть разные способы. IOPL у меня стоит в 0, не помню зачем.
VMProg код на языке 8086 вызывающий прерывание и возвращающийся назад в защищенный режим.
Код VMProg копируется в первый мегабайт. Со страницами возиться не стал. В первом мегабайте отводиться так же буфер под данные.
Далее идут нюансы обработки прерываний и привилегированных команд. Порты у меня тоже были привилегированными, зря конечно.
Далее забил так как требовалось много команд эмулировать программно.
К тому же обработка прерываний усложняется. Надо проверить флаг эмуляции после эмулировать нужное прерывание программно.
Код:
var
VMProg:array [0..29] of Byte=($9C,$0E,$6A,$09,$64,$FF,$2E,$40,$00,$66,$9C,$66,$67,$81,$34,$24,
$00,$00,$02,$00,$6A,$08,$66,$68,$00,$00,$10,$00,$66,$CF);
label
EndRealInt;
// JampVM;
procedure InitRealInt;
var p:Pointer;
begin
asm
mov eax,DWord(EndRealInt)
mov DWord PTR [VMProg+18h], eax
xor eax,eax
mov ax,Word PTR [eax+413h] // Размер Base Memory kb
shl eax,10 // *1024
sub eax, 64*1024 //-64kb сегмент для наших нужд
mov DWord PTR [p],eax
//move DWord PTR [JampVM],eax
end;
move(VMProg[0],p^, SizeOf(VMProg));
end;
procedure RealInt;
assembler;
asm;
push ebp
push eax
pushf
and Word [esp], not 4000h //Сбрасываем NT флаг В 0
and Word [esp], not 3000h //Устанавливаем IOPL В 0
popf
xor ebp,ebp
mov bp,Word PTR [ebp+413h] // Размер Base Memory kb
shl ebp,6 // *1024/16
sub ebp, 64*1024/16
shl ebp, 4
mov al, Byte PTR [esp+12] // Номер прерывания из стека
shl al,2 // *4
mov Byte PTR [ebp+7h], al // Сохроняем в код виртуального режима
pop eax
shr ebp, 4
push 0 //GS, FS, DS,ES
push 0
push ebp
push ebp
push ebp //SS
push 0ffffh //ESP
pushfd //EFlag
push ebp //cs
push 0 //EIP
xor Dword [esp+8], 20000h // Изменяем VM флаг
iretd
EndRealInt:
pop ebp
ret
end;