V86 ? howto ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
aladdin

V86 ? howto ?

Post 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.
ASHLEY4

Re:V86 ? howto ?

Post by ASHLEY4 »

Have tryed my vesademo that switch to and from realmode for vesa switching?.

\\\\||////
(@@)
ASHLEY4.
aladdin

Re:V86 ? howto ?

Post 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.
Ozguxxx

Re:V86 ? howto ?

Post 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.
Ozguxxx

Re:V86 ? howto ?

Post by Ozguxxx »

Dreamsmith

Re:V86 ? howto ?

Post 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;
   }
}
aladdin

Re:V86 ? howto ?

Post by aladdin »

thank you ;)
i'll try all this, and inform you about results .
Ozguxxx

Re:V86 ? howto ?

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:V86 ? howto ?

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:V86 ? howto ?

Post 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)
Post Reply