v86 help

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.
Tom

v86 help

Post by Tom »

Hello, i put some of john fine's code into my OS, but when I call "call_BIOS(...);" it reboots my computer :(

I have no idea how this works, could anyone help me?

here is the v86.asm ( my version ) code:

; includes:
%include 'intframe.inc' ; from john fine's code

GLOBAL   call_BIOS
GLOBAL   call_V86

%define args 12

;************************************************************************************************************

call_BIOS:
   push   ebx
   push   esi
   push   edi
   push   ebp
%assign args 20
   mov   ebp, esp
   mov   ebx, [ebp+args]      ;Before frame
   mov   cl, [ebp+args+12]   ;AH value
   mov   [fr.ah+ebx], cl      ;Put it into before frame
   mov   eax, [ebp+args+8]   ;Interrupt number
   mov   eax, [ZERO+eax*4]   ;Get the vector
   movzx   edx, ax         ;Extend IP part to EIP
   shr   eax, 16         ;Get CS part
   mov   [fr.eip+ebx], edx   ;Put EIP in before frame
   mov   [fr.cs+ebx], eax   ;Put CS in before frame
   mov   dword [fr.eflags+ebx], 0x23002
   jmp short call_V86.1      ;Merge with main entry point

; void call_V86(INTFRAME *before, INTFRAME *after);
;
; Pushes three words (for iret or far ret) on the current v86 mode
; stack.
;
; Changes the p_ds, p_es, esp and ss fields in the before frame to
; allow that frame to be used to transfer control to V86 mode.
;
; When that v86 mode code exits with iret or far ret, the registers
; are put in the after frame, and the caller of call_V86 is resumed.
;
call_V86:
   push   ebx
   push   esi
   push   edi
   push   ebp
   mov   ebx, [esp+args]      ;Before frame
.1:   xor   eax, eax      ;Need NULL p_ds and p_es for
   mov   [fr.p_ds+ebx], eax   ; standard INT_EXIT macro for V86
   mov   [fr.p_es+ebx], eax

   pushf               ;Save interrupt enable bit
   mov   esi, [v86k_esp]         ;Get existing V86 frame limit
   push   dword [esp0]         ;Save esp0
   push   esi            ;Save V86 frame limit
%assign args args+12            ;Count 3 more dwords on stack
   cli               ;Can't allow interrupts between
                  ;changing esp0 and IRETing
   mov   [esp0], esp         ;Set new V86 frame limit
   mov   [v86k_esp], esp
   movzx   eax, word [fr.sp+esi-fr_size]   ;Get V86 sp
   movzx   ecx, word [fr.ss+esi-fr_size]   ;Get V86 ss
   sub   eax, byte 6         ;Make room on V86 stack
   mov   [fr.esp+ebx], eax      ;Store in before frame
   mov   [fr.ss+ebx], ecx
   shl   ecx, 4            ;V86 stack segment base

   mov dword [ZERO+eax+ecx+2], 0x3002FFFF   ;Create a return point for the
   mov word [ZERO+eax+ecx], unwind_sw   ;V86 routine at FFFF:unwind_sw
   mov   esp, ebx         ;Use before frame as a stack
   INT_EXIT

unwind_sw: int   46h            ;Get out of V86 mode
;************************************************************************************************************

tss: dd 0
esp0: dd stack0top
   resb   0x66 - 0xC
   dw   0x68
; I/O restrictions
   resb   8192         ;0 - FFFF unrestricted
tss_size equ $-tss

v86k_esp dd   stack0top

   resd   4096
stack0top:

here is my kernel32.c:

/* kernel32.c : FritzOS C Kernel            
Copyright (C) 2002 Tom Fritz

* This program is a part of the FritzOS kernel, and may be freely
* copied under the terms of the GNU General Public License (GPL),
* version 2, or at your option any later version.

For more info, look at the COPYING file.
*/

asm("jmp start");      // go to Start

#include "include/fstdio.h"
#include "include/graphics.h"

#include "include/intframe.h" ; from john fine's header file

extern void call_BIOS( INTFRAME* before, INTFRAME* after, int number, char ah );

void start()
{
/*   k_printf( "FritzOS has loaded it\'s C kernel.", RED_GREEN, 1 );

   k_printf( "FritzOS Prekernel0.5, Copyright (C) 2002 Tom Fritz", RED_GREEN, 3 );
   k_printf( "FritzOS comes with ABSOLUTELY NO WARRANTY; for details look at COPYING.", WHITE_BLACK,
      4 );

   k_printf( "This is free software, and you are welcome to redistribute it under certain",
      WHITE_BLACK, 5 );

   k_printf( "conditions; look at COPYING for details.", WHITE_BLACK, 6 ); */

   INTFRAME* hm1, * hm2;

   call_BIOS( hm1, hm2, 10, 3 );

   Freeze();
}

// End of kernel32.c
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 help

Post by Pype.Clicker »

in order to handle V86 mode, you need a powerful GPF handler that will detect you're calling it from v86 mode and that will emulate things like software interrupt calls, etc...

If you have no GPF handler or if it just tries to return, there are chances that your code will issue a triple fault ...
Tom

Re:v86 help

Post by Tom »

oh, ty, but what is that? & how could I make a whateveryousaid thing?
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 help

Post by Pype.Clicker »

First, you must have a working IDT installed and write an exception handler for General Protection Fault (the infamous 0x0d exception -- segfault). Before using it in the context of V86, check it works by loading an invalid selector in some register and try using it ...

when this works (i.e. once you can display a message on screen saying "general protection at cs=xxxx, eip=xxxxxxxx"), you will have to find out the difference between a GPF generated by a "normal" task or by a "v86" task (this can be done by checking the VM flag in the eflags stored on the stack).

Now you'll be able to print "general protection @ ..." or "v86 event @ ...". What you'll have to do next is to extract cs=xxxx and ip=xxxx from the stack, compute the effective address of CS*16+IP where realmode instruction raised the exception and see what you have for an opcode around there ...

If this is an INT yy, extract the yy byte, read the real-mode IVT (interrupt vector table) at position yy and then do the job of the CPU : push old CS and IP on the REAL MODE stack (with realmode eflags), and replace the ones saved on the exception stack by those stored in the IVT, then return ...

uh, and, by the by, if yy == the interrupt you reserved for halting V86 service ... just halt the service (i.e. don't return to the interrupted task ;)
Tom

Re:v86 help

Post by Tom »

ok... with that info... i'm thinking What in the World
am I doing here!!! I'm just a DOS programmer!!
Not an OS programmer ( although I did get some done ).

I will base my kernel off of someone elses, untill I know
enough of v86 mode.

Does anyone have a v86 kernel ( but not so extremly huge )?

Thank you, Tom
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 help

Post by Pype.Clicker »

there is V86 support in TRAN's start32 tutorial.
see http://www.mega-tokyo.com/forum/index.p ... 90;start=0
Schol-R-LEA

Re:v86 help

Post by Schol-R-LEA »

Keep in mind that there is no such thing as a 'v86-mode kernel', per se. There are real-mode kernels, and there are protected-mode kernels. V86 mode is a special case of protected mode which allows you to run real mode programs, that's all. In order to run v86 mode, you have to have a working p-mode kernel first, even if only a very simple one.

What is your purpose in setting up v86 support? Do you want or need to use the BIOS for something? Do you intend to support existing real-mode software? Do you intend to simulate MS-DOS? How you design your system will depend on your goals.

I'd really suggest reading up on p-mode and v86 mode, and getting a solid undertanding of how it works, or you'll just keep fumbling about in the dark. OS design is one area where you cannot afford to be ignorant of anything your code does.
Tom

Re:v86 help

Post by Tom »

Well, ty Pype.Clicker, i'll try that tutorial, I can't test it right now.

To Schol-R-LEA, I intend to make my OS have DOS support, & use the BIOS.

I do know about Protected mode well, v86 mode confuses me.

After I see & test working code, it isn't confusing, for some strange reason ???
Tom

Re:v86 help

Post by Tom »

Pype.Clicker, I tried the code (start32.asm) and it doesn't compile :(. I use nasm 98 on Mandrake Linux. There's tons of errors I can't correct when I compile it.
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 help

Post by Pype.Clicker »

this is TASM/MASM code ... there was no NASM in 1993 ...
Take it as an exercise: rewrite it for nasm, so you'll have to understand what happens and why :-)

or find an abandonware version of tasm
Tom

Re:v86 help

Post by Tom »

ty for TASM 3.1 ;D

But I did find a NASM version of the v86 tut you gave me, I compiled it and it worked, I tested it once, I need to test it more.
Tom

Re:v86 help

Post by Tom »

TY pype.clicker!!! after I found a working NASM version of that tutorial...I can get in to v86 mode! ( in DOS ).

All I need to do is change it to my bootsector, and put it in my C kernel!

;D

Now I can work on FS, in my OS... it'll be very complicated, I think, because Stability is the #1 issue in FritzOS.
Tom

Re:v86 help

Post by Tom »

it works in DOS, but when I changed it for my bootloader.. it sets pmode, but when I do a v86 int nothhing happens:

mov byte [v86r_ax], 13h
mov al, 10h
int 30h
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 help

Post by Pype.Clicker »

nothing should prevent you to call the BIOS from your bootloader as you did from DOS ... except maybe if you overwrite some BIOS datas (IVT, Bios variables area ...) when booting (typical in hobby-OS)
Tom

Re:v86 help

Post by Tom »

I put the v86 tutorial on the disk, after the bootloader.

I know it(tutorial) sets Pmode OK, because of that, I know it runs untill there ( I know that because I didn't stop teh floppy motor from spinning ).

What whould have made it overwrite something?
my bootloader doesn't have a GDT or PMode. ( i'm using prekernel0-2's bootloader), it just jumps to the turorial.

if I sound weird, it's because I didn't have enough time to type this.
Post Reply