Page 1 of 1
V86 ? howto ?
Posted: Thu Sep 23, 2004 6:48 am
by aladdin
I implemented a basic multitasking on my os, it seems that everytings works well, now, I want to add a simpl v86 support, to have access to bios INTs coze I want to developpe a vesa interface.
can anyone help me with links, examples ...etc.
Re:V86 ? howto ?
Posted: Thu Sep 23, 2004 7:05 am
by ASHLEY4
Have tryed my vesademo that switch to and from realmode for vesa switching?.
\\\\||////
(@@)
ASHLEY4.
Re:V86 ? howto ?
Posted: Thu Sep 23, 2004 7:29 am
by aladdin
I dont like this methode
I prefer to use V86, because i will need it in the future, so, I think it's a good idea to start searching now.
Re:V86 ? howto ?
Posted: Thu Sep 23, 2004 11:29 am
by Ozguxxx
Tim Robinson's vm86 tutorial is the perfect source for implementing basic vm86 support. I needed nothing else, other than 80386 manual. At first sight tutorial seems rather complicated but it is not that hard. Even the gpf handler to handle opcodes is included, I used this code to implement vm86 gpf handler. (with reference of course. ;D) Other than this, it explains basics about vm86 memory, opcodes and other stuff... Good luck.
Re:V86 ? howto ?
Posted: Thu Sep 23, 2004 11:29 am
by Ozguxxx
Re:V86 ? howto ?
Posted: Thu Sep 23, 2004 9:45 pm
by Dreamsmith
I think Tim's tutorial is pretty good, too, but actually he makes it more difficult than it needs to be. Just stuffing your normal code's TSS segment descriptor into the GPF's vector in the IDT allows you to bounce in and out of V86 mode using a threaded coding style, examining the various fields of the TSS for register values and such; much easier than trying to write a GPF interrupt handler state-machine style. Performing a task switch for each V86 monitor operation is probably a little slower, but not noticably so.
Here's my own V86 monitor, written multitasking style and with support for a couple of opcodes that were missing from Tim's tutorial IIRC:
Code: Select all
INLINE void v86push16(UInt16 x)
{
v86.tss.esp = (UInt16)(v86.tss.esp - 2);
*(UInt16*)(v86.tss.ss * 16 + v86.tss.esp) = x;
}
INLINE void v86push32(UInt32 x)
{
v86.tss.esp = (UInt16)(v86.tss.esp - 4);
*(UInt32*)(v86.tss.ss * 16 + v86.tss.esp) = x;
}
INLINE UInt16 v86pop16(void)
{
UInt16 result = *(UInt16*)(v86.tss.ss * 16 + v86.tss.esp);
v86.tss.esp = (UInt16)(v86.tss.esp + 2);
return result;
}
INLINE UInt32 v86pop32(void)
{
UInt32 result = *(UInt32*)(v86.tss.ss * 16 + v86.tss.esp);
v86.tss.esp = (UInt16)(v86.tss.esp + 4);
return result;
}
void callV86(UInt16 segment, UInt16 offset)
{
int o32 = 0, a32 = 0;
UInt32 err;
v86.tss.cs = segment;
v86.tss.eip = offset;
v86.tss.eflags = (v86.tss.eflags & EFLAGS_REAL) | EFLAGS_VM;
disablePreemption(currentTask); // disallow multitasking for the moment
setTaskHandler(0x0D, currentTask->selector, 0); // this task is GPF handler
ljmp(v86selector); // switch to V86 task
err = pop(); // pop GPF error code
for (;;)
{
UInt8 *ip = (UInt8*)(v86.tss.cs * 16 + v86.tss.eip);
switch ( *ip )
{
case 0x66: // O32
o32 = 1;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
continue;
case 0x67: // A32
a32 = 1;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
continue;
case 0x9C: // PUSHF
if ( o32 )
v86push32(v86.tss.eflags);
else
v86push16(v86.tss.eflags);
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0x9D: // POPF
if ( o32 )
v86.tss.eflags = (v86pop32() & EFLAGS_REAL) | EFLAGS_VM;
else
v86.tss.eflags = (v86pop16() & EFLAGS_REAL) | EFLAGS_VM;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0xCC: // INT 3
case 0xCD: // INT x
v86push16(v86.tss.eflags);
v86push16(v86.tss.cs);
v86push16(v86.tss.eip + (ip[0] - 0xCB));
v86.tss.eip = *(UInt16*)(ip[0] == 0xCC ? 12 : ip[1] * 4);
v86.tss.cs = *(UInt16*)(ip[0] == 0xCC ? 14 : ip[1] * 4 + 2);
v86.tss.eflags &= ~(EFLAGS_IF | EFLAGS_TF);
break;
case 0xCF: // IRET
v86.tss.eip = v86pop16();
v86.tss.cs = v86pop16();
v86.tss.eflags = (v86pop16() & EFLAGS_REAL) | EFLAGS_VM;
break;
default:
dprintf("V86 unknown opcode: %02X (err=%04X)\n", *ip, (UInt16)err);
dumpTSS(&v86.tss);
// The ability in C to fall through into the next case is an
// outstanding feature of the language, not a design flaw.
case 0xF4: // HLT
setEFLAGS(getEFLAGS() & ~EFLAGS_NT); // clear Nested Task flag
resetTaskSelector(v86selector); // clear busy bit on V86 task
setIntHandler(0x0D, handler0D); // reset standard GPF handler
enablePreemption(currentTask); // reenable multitasking
return; // ...and I am outta here...
case 0xFA: // CLI
v86.tss.eflags &= ~EFLAGS_IF;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
case 0xFB: // STI
v86.tss.eflags |= EFLAGS_IF;
v86.tss.eip = (UInt16)(v86.tss.eip + 1);
break;
}
iret(); // return to V86 task
err = pop(); // pop GPF error code off stack
o32 = a32 = 0;
}
}
Re:V86 ? howto ?
Posted: Fri Sep 24, 2004 2:29 am
by aladdin
thank you
i'll try all this, and inform you about results .
Re:V86 ? howto ?
Posted: Tue Nov 30, 2004 10:02 am
by Ozguxxx
Hi, I have a question about priviledged instructions, are address 32 and operand 32 prefix priviledged in v86? They should be but in bochs they are not creating gpf in v8086 mode, or Im doing somting wrong. Thanx in adv.
Re:V86 ? howto ?
Posted: Tue Nov 30, 2004 10:15 am
by Brendan
Hi,
Ozgunh82 wrote:
Hi, I have a question about priviledged instructions, are address 32 and operand 32 prefix priviledged in v86? They should be but in bochs they are not creating gpf in v8086 mode, or Im doing somting wrong. Thanx in adv.
AFAIK the address and operand size override prefixes can be used in any CPU mode (including real mode and V86 mode), and shouldn't cause any exception.
If you use the address size override prefix to access past 64 Kb in real mode or V86 mode you will get a GPF fault (just like accessing past a segment limit in protected mode), so the 32 bit address override prefix isn't actually useful for anything except 32 bit segments. The operand size override is very useful though
.
Cheers,
Brendan
Re:V86 ? howto ?
Posted: Tue Nov 30, 2004 11:05 am
by Pype.Clicker
Brendan wrote:
so the 32 bit address override prefix isn't actually useful for anything except 32 bit segments.
don't quite agree ... the address override also means you can do [some_array+eax+ecx*4] while 8086 addressing is limited to bp,sp,bx,si,di for addressing and only accepts some combinations (like bx+si, but not si+di, for instance)