home *** CD-ROM | disk | FTP | other *** search
- .387
- ;
- ; prot.asm - Protected mode assembler code for gserver
- ;
- ;************************************************************************/
- ;* Copyright (C) 1986-1993 Phar Lap Software, Inc. */
- ;* Unpublished - rights reserved under the Copyright Laws of the */
- ;* United States. Use, duplication, or disclosure by the */
- ;* Government is subject to restrictions as set forth in */
- ;* subparagraph (c)(1)(ii) of the Rights in Technical Data and */
- ;* Computer Software clause at 252.227-7013. */
- ;* Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138 */
- ;************************************************************************/
- ;
-
- ;
- ; Here we define the segments in this module to force their
- ; ordering.
- ;
-
- CODESEG segment public byte 'CODE'
- CODESEG ends
-
- DATASEG segment public dword 'DATA'
- DATASEG ends
-
- ;
- ; Global data
- ;
- DATASEG segment
-
- ebpsave dd ? ; Saved protected mode EBP
- espsave dd ? ; Saved protected mode ESP
- sssave dw ? ; Saved protected mode SS
-
- ssexit dw ? ; Saved SS for exit
- espexit dd ? ; Save ESP for exit
-
- exitflag dw 0 ; Exiting from real mode server flag
-
- ;
- ; EXEC parameter block for EXEC to load real mode server
- ;
- ldparm dd 0 ; Environment offset
- dw 0 ; Environment selector
- dd offset cmdtail ; Offset of the command tail
- dw 14h ; Selector of the command tail
-
- ;
- ; We pass some parameters to the real mode server in the DOS command tail
- ;
- cmdtail db 12 ; Length of the command tail is 12
- callback dd ? ; real mode FAR ptr to 386|DOS-X routine to
- ; call protected mode
- dd protret ; address of "protret" entry point the real
- ; mode server calls after it initializes
- protcs dw ? ; protected mode CS
- protpsp dw ? ; Protected mode program's PSP
- db 0dh ; CR to make DOS happy
-
- TRUE equ 1
- FALSE equ 0
- fp387f dd ? ; T ==> 387 present, F ==> not present
- prot_387state db 108 dup (?) ; protected mode pgm floating point state
-
- ;
- ; Special stack used only during the EXEC call
- ;
- align 4
- db 128 dup (?)
- exec_stack label byte
-
- DATASEG ends
-
- assume cs:CODESEG,ds:DATASEG
-
- CODESEG segment
-
- ;
- ; realload - Load and initialize a real mode driver
- ;
- ; retcode = realload(filenamep, srvptrp, exe_blockp);
- ;
- ; int retcode; /* Return code */
- ; char *filenamep; /* Pointer to the file name */
- ; REALPTR *srvptrp; /* returned; real mode FAR address
- ; of server interface routine */
- ; EXEC_BLK *exe_blockp; /* Pointer to parameter block used to
- ; load real mode server */
- ;
- ; This routine loads the real mode server program.
- ; The caller passes in the file name of
- ; the server to be loaded. No path searching is done by the routine for
- ; file therefore a complete file path must be given for the file or the
- ; file must be located in the current directory. If the load is
- ; successful, then the return code is set to zero and the real mode
- ; address in segment:offset format of the server is returned
- ; to the caller. The server is called by passing this address to
- ; the routine "realcall". If the load is unsuccesful, then the return
- ; code is set to one of the following MS-DOS error codes:
- ;
- ; 2 = File not found or invalid path
- ; 5 = Access denied
- ; 8 = Not enough memory to load program
- ; 10 = Invalid environment segment
- ; 11 = Invalid file format
- ;
- public realload ; Publics for High C/C++
- public _realload ; Publics for Microsoft C/C++
- public realload_ ; Publics for Watcom C/386
-
- realload proc near
- _realload:
- realload_:
- ;
- ; Stack frame
- ;
- #filenamep equ dword ptr [ebp + 8] ; File name pointer
- #srvptrp equ dword ptr [ebp + 12] ; Pointer to returned server address
- #exe_blockp equ dword ptr [ebp + 16] ; Pointer to EXEC parameter block
-
- push ebp ; Set-up a stack frame and save registers
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push edx ;
- push edi ;
- push esi ;
- push es ;
-
- ;
- ; If we have a 387 present, save the floating point state so we can restore
- ; it again after the real mode program initializes. (It's not necessary
- ; to save the state if there's no coprocessor and we're emulating, since
- ; the real mode and prot mode emulators won't interfere with each other.
- ; Since we don't unconditionally do an FSAVE/FRSTOR, someone could pick up
- ; this glue code and use it with a non-floating-point program without
- ; having it break on a machine without a coprocessor).
- ;
- mov fp387f,FALSE ; assume no coprocessor
- int 11h ; branch if no coprocessor
- test eax,2 ;
- jz short #no_87 ;
- mov fp387f,TRUE ; flag coprocessor present
- fsave prot_387state ; save current coprocessor state
- #no_87:
-
- ;
- ; Complete the parameter block that we pass to the real mode server in
- ; the DOS command tail
- ;
- mov ah,51h ; protected mode program's PSP
- int 21h ; on the stack
- mov protpsp,bx ;
-
- mov protcs,cs ; Save the CS register for our protected mode
- ; return address. The offset is filled in
- ; at link time.
-
- mov ax,250DH ; Get the real-to-protected mode
- int 21h ; call-back address and save it in our
- mov callback,eax ; parameter block.
-
- ;
- ; Now EXEC to the real mode program. Before making the EXEC call, switch
- ; to a temporary stack buffer that we use just for the EXEC. This is
- ; because after the real mode server initializes, we will return from
- ; this routine and continue using our current stack. Later on, when
- ; we tell the real mode server to terminate, the INT 21h from the EXEC
- ; call will return, on the same stack it was on when the INT 21h was made --
- ; so if we didn't have a temp stack we'd be stepping on the current stack,
- ; which by that time might be in use again (if realexit() is down more
- ; levels of function calls than realload() is).
- ;
- mov ebpsave,ebp ; Save our current EBP and SS:ESP in globals
- mov espsave,esp ;
- mov sssave,ss ;
-
- mov edx,#filenamep ; get filename ptr before switching stacks
-
- lea esp,exec_stack ; switch to temp EXEC stack
-
- lea ebx,ldparm ; EXEC to the real mode server normally
- mov ax,ds ;
- mov es,ax ;
- mov ax,4B00h ;
- int 21H ;
-
- jc #err ; Branch if a load error. Error return code
- ; is already in EAX
-
- jmp exitret ; EXEC returns successfully when the real
- ; mode server terminates. This only
- ; occurs when we tell it to terminate
- ; by calling the realexit() routine.
- ; So jump back into the point in the
- ; realexit() routine where it makes the
- ; real mode server terminate.
-
- ;
- ; After the real mode server loads and initializes, it uses the 386|DOS-X
- ; service to call through to protected mode to the "protret" label, whose
- ; address we passed to the server in the command tail. The real mode
- ; server passes the real mode FAR address of the server function in EAX.
- ;
- ; When we get here, we are on the real mode server's stack, and the current
- ; PSP is the real mode server's PSP. We want to get back on our own stack,
- ; switch back to our own PSP, and return to the caller of realload().
- ;
- protret:
-
- mov ssexit,ss ; Save the current stack for when we
- mov espexit,esp ; want to return to the real mode
- ; code in order to force an exit.
-
- mov ebp,ebpsave ; Switch back to our regular stack.
- mov ss,sssave ;
- mov esp,espsave ;
-
- mov ebx,#srvptrp ; Return the server function pointer in the
- mov [ebx],eax ; real mode code to the caller.
-
- mov bx,protpsp ; Switch back to the protected mode pgm's PSP
- mov ah,51h ;
- int 21h ;
-
- cmp fp387f,FALSE ; Restore the prot mode pgm's 387 state
- je short #no_87_rst
- frstor prot_387state
- #no_87_rst:
-
- sub eax,eax ; Zero the return to indicate a successful
- ; load.
-
- #ret: pop es ; Restore the registers and return
- pop esi ;
- pop edi ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
- ret ;
-
- #err: mov ebp,ebpsave ; Switch back to our normal stack
- mov ss,sssave ;
- mov esp,espsave ;
- jmp #ret ; Go return
-
- realload endp
-
-
- ;
- ; realexit - Force the real mode code to exit
- ;
- ; realexit();
- ;
- ; The "realexit" routine is called to force the real mode server to
- ; exit. It must be called by the protected mode code so that the
- ; memory allocated to the real mode code is freed and the real mode
- ; open files are closed.
- ;
- public realexit
- public _realexit
- public realexit_
-
- realexit proc near
- _realexit:
- realexit_:
-
- push ebp ; Set-up a stack frame.
- mov ebp,esp ;
- push ebx ;
- push ecx ;
- push edx ;
- push edi ;
- push esi ;
- push es ;
-
- mov ebpsave,ebp ; Save our current EBP and SS:ESP in globals
- mov espsave,esp ;
- mov sssave,ss ;
-
- mov exitflag,1 ; Turn on the flag that says we are telling
- ; the real mode server to exit.
-
- ;
- ; Now "tell" the real mode server to exit.
- ; We do this by returning from the original call through to protected mode
- ; (to label "protret") that the server made way back when it first initialized.
- ; To return from that call, all we have to do is switch back to the stack
- ; we were on at that point (which we saved in globals), and execute
- ; a FAR return instruction.
- ;
- mov ss,ssexit ; Reload SS:ESP.
- mov esp,espexit ;
- db 0cbh ; Use a far return instruction to go back
- ; to the real mode code.
-
- ;
- ; When the server terminates, it returns from the original INT 21h func 4Bh
- ; EXEC that was done in the realload() routine. That routine then immediately
- ; jumps to the "exitret" label below.
- ;
- ; When we get here, the real mode server and its PSP are gone, and we are
- ; back on our own PSP. However, the stack is the temp EXEC stack that we
- ; switched to just before making the original INT 21h func 4Bh call.
- ; So we have to switch back to the stack we had when realexit() was called.
- ;
- exitret:
-
- ;
- ; If the real mode server exited before we told it to by returning from
- ; that initialization time call to "protret" above, then we are hosed,
- ; because we have no idea where in the protected mode program we are
- ; executing.
- ;
- cmp exitflag,0 ; Branch if the exit flag is off. (oops!)
- je #err ;
-
- mov ebp,ebpsave ; Switch back to our regular stack.
- mov ss,sssave ;
- mov esp,espsave ;
-
- mov exitflag,0 ; Clear the exit flag.
-
- pop es ; Restore the registers and return.
- pop esi ;
- pop edi ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
- ret ;
-
- #err: mov edx,offset #errmsg ; Output error message "Fatal error:
- push cs ; Unexpected exit from real mode code.".
- pop ds ;
- mov ah,09h ;
- int 21h ;
-
- mov ax,4c01h ; Exit ourselves.
- int 21h ;
-
- #errmsg db 'Fatal error: Unexpected exit from real mode code.'
- db 0dh,0ah,'$'
-
- realexit endp
-
- CODESEG ends
-
- end
-