Уже месяц пишу. Так долго потому что пишу по выходным. Обработчик эмулирует запрeщенные команды. Код пишется из расчета 486 процессора. Пока не все добавил Ничего непонимаю. Тестирую на Borchs, Почемуто процессор выходит в защищенный режим на EIP=0. Обработчик #GP Код (Text): test DWord [esp+12],20000h // Проверяем VM флаг jz @err // ошибка исключение // Привелегированные инструкции. push eax push ebx mov ax, DS_DESCR mov ds,ax mov es,ax xor eax, eax mov eax,DWord [esp+8+8] //cs shl eax,4 add eax,DWord [esp+4+8] //eip xor ebx, ebx mov ebx,[esp+5*4+8] // Old SS shl ebx,4 add ebx, [esp+4*4+8] // Old ESP cmp byte [eax],0FAh //CLI jne @a1 //and word [esp+3*4+8], not 200h //1 000 000 000b=200h inc DWord [esp+4+8] // EIP +1 jmp @_end @a1: cmp byte [eax],0FBh //STI jne @a2 or word [esp+3*4+8], 200h //1 000 000 000b=200h inc DWord [esp+4+8] // EIP +1 jmp @_end @a2: cmp byte [eax],9Ch //PUSHF jne @a3 add word [esp+4*4+8],-2 // Old ESP mov ax, word [esp+3*4+8] // Old EFLAGS mov word [ebx-2], ax inc DWord [esp+4+8] // EIP +1 jmp @_end @a3: cmp byte [eax],9Dh //POPF jne @a4 mov ax,word [ebx] mov word [esp+3*4+8],ax // Old EFLAGS add word [esp+4*4+8],+2 // Old ESP inc DWord [esp+4+8] // EIP +1 jmp @_end @a4: cmp byte [eax],0CDh //INT xx jne @a5 add eax,2 mov Word [ebx+6], ax // IP shr eax,16 shl eax,12 mov Word [ebx+4], ax // CS mov ax, Word [esp+3*4+8] //FLAGS mov Word [ebx+2], ax add word [esp+4*4+8],-6 // Old ESP xor eax, eax mov eax,DWord [esp+8+8] //cs shl eax,4 add eax,DWord [esp+4+8] //eip xor ebx,ebx mov bl, [eax+1] shl ebx, 2 mov ax,[ebx+2] mov Word [esp+8+8], ax //Old CS mov ax,[ebx] mov Word [esp+4+8], ax //Old EIP jmp @_end @a5: cmp byte [eax],0CFh //IRET jne @a6 mov ax,word [ebx+4] // FLAGS mov word [esp+3*4+8],ax // Old EFLAGS mov ax,word [ebx+2] // CS mov Word [esp+8+8], ax //Old CS mov ax,word [ebx] // IP mov Word [esp+4+8], ax //Old EIP add word [esp+4*4+8],6 // Old ESP jmp @_end @a6: cmp byte [eax],0ECh //IN AL,DX jne @a7 IN AL,DX mov Byte [esp+4], al inc DWord [esp+4+8] // EIP +1 jmp @_end @a7: cmp byte [eax],0EDh //IN AX,DX jne @a8 IN AX,DX mov Word [esp+4], ax inc DWord [esp+4+8] // EIP +1 jmp @_end @a8: cmp word [eax],0ED66h //IN EAX,DX jne @a9 IN EAX,DX mov DWord [esp+4], eax add DWord [esp+4+8],2 // EIP +2 jmp @_end @a9: cmp byte [eax],6Ch //INSB jne @a10 INSB mov Byte [esp+4], al inc DWord [esp+4+8] // EIP +1 jmp @_end @a10: cmp byte [eax],6Dh //INSW jne @a11 INSW mov Word [esp+4], ax inc DWord [esp+4+8] // EIP +1 jmp @_end @a11: cmp word [eax],6D66h //INSD jne @a12 INSD mov DWord [esp+4], eax add DWord [esp+4+8],2 // EIP +2 jmp @_end @a12: cmp byte [eax],0EEh //OUT DX, AL jne @a13 mov eax,[esp+4] OUT DX, AL inc DWord [esp+4+8] // EIP +1 jmp @_end @a13: cmp byte [eax],0EFh //OUT DX, AX jne @a14 mov eax,[esp+4] OUT DX, AX inc DWord [esp+4+8] // EIP +1 jmp @_end @a14: cmp word [eax],0EF66h //OUT DX, EAX jne @a15 mov eax,[esp+4] OUT DX, EAX add DWord [esp+4+8],2 // EIP +2 jmp @_end @a15: cmp byte [eax],6Eh //OUTSB jne @a16 mov eax,[esp+4] OUTSB inc DWord [esp+4+8] // EIP +1 jmp @_end @a16: cmp byte [eax],6Fh //OUTSW jne @a17 mov eax,[esp+4] OUTSW inc DWord [esp+4+8] // EIP +1 jmp @_end @a17: cmp word [eax],6F66h //OUTSD jne @a18 mov eax,[esp+4] OUTSD add DWord [esp+4+8],2 // EIP +2 jmp @_end @a18: @_end: pop ebx pop eax add esp,4 IRETD @err: MOV AX,0Dh CALL DebugPRint; IRETD Походу срыв стека, но както внезапно. Т.е идет все хорошо, а потм бац и все падает.
Вот здесь Код (Text): cmp byte [eax],0CDh //INT xx jne @a5 add eax,2 mov Word [ebx+6], ax // IP shr eax,16 shl eax,12 mov Word [ebx+4], ax // CS mov ax, Word [esp+3*4+8] //FLAGS mov Word [ebx+2], ax знак в трёх местах при [ebx+A] случайно не перепутан?
В принципе код ещё не учитывает того, что insb, который вводит байт по адресу es:di, в V86-режиме и в защищённом режиме пишет в общем случае в разные области памяти (база es может быть разной) и аналогично для прочих команд этой серии, но по логике на eip это никак влиять не должно... Попробуй в TSS создать I/O permission map, забитую нулями - так #GP не будет генерироваться для команд работы с портами, что позволит выяснить, какая часть эмуляции глючит. Кстати, а образ для Bochs выложить можешь?
Вообщем както странно. Вызываю прерывание реального режима int 10h В итоге поподаю на Hlt смущает адресс инструкции 0000:0004 Вызываю int 12h прерывание выполняется удачно. Даже не знаю почему так. =( Может EFLAGS надо лучши обрабатывать? diamond , можно попробовать. Хотя в int 10h там out dx,al используют.
Pavia А ты учитываешь, что обработчик прерывания имеет право выходить не по IRET, а по RETF 2? Причём retf не генерирует #GP, так что если перед вызовом прерывания в V86-стек не кладётся правильный адрес возврата, то скорее всего в 0000:0000 и вернётся, а там до исключения недалеко. Я, правда, не в курсе, использует ли это Bochs'овский int 10h, но в int 13h такое практикуется на каждом шагу.
diamond Разрешил все порты эффект тот же. Походу стек срывается непонимаю почему. И далее проц делает неправельные возвраты. А все понял.
Pavia немного не по теме, но все же у тебя INT неправильно эмулируется семантика INT реального режима подразумевает сброс IF, TF и AC после сохранения FLAGS т. е Код (Text): ... mov Word [esp+4+8], ax //Old EIP and DWord [esp + 3 * 3 + 8], 0FFFBFCFFh jmp @_end @a5:
rei3er Все понял да int неправельно эмулировался Код (Text): add eax,2 mov Word [ebx+6], ax // IP shr eax,16 shl eax,12 mov Word [ebx+4], ax // CS Это бред. Заменил на Код (Text): mov ax,Word [esp+4+8] //old eip add ax,2 mov Word [ebx-6], ax // IP mov ax,Word [esp+8+8] //Old cs mov Word [ebx-4], ax // CS Вопрос как правельно если сегмент 64битный и регистр к примеру ip и sp выходит за гроницу то что делать?
rei3er Только Push сначало, а потом сброс флагов. Чтобы можно было востановить. А тут вопрос AC он же 18бит, а в стек кладуться только биты с 0 по 15 в чем подвох?
кладутся то 16 бит, а вот после сохранения сбрасывается AC в EFLAGS по крайней мере так написано в спецификации на INT реального режима IP переполняется и становится равным >= 0 при детекте переполнения SP генерируется #SS