home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l350 / 3.ddi / EXAMPLES / GDEMO / PROT.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-12-24  |  10.5 KB  |  352 lines

  1.     .387
  2. ;
  3. ;    prot.asm - Protected mode assembler code for gserver
  4. ;
  5. ;************************************************************************/
  6. ;*    Copyright (C) 1986-1993 Phar Lap Software, Inc.            */
  7. ;*    Unpublished - rights reserved under the Copyright Laws of the    */
  8. ;*    United States.  Use, duplication, or disclosure by the         */
  9. ;*    Government is subject to restrictions as set forth in         */
  10. ;*    subparagraph (c)(1)(ii) of the Rights in Technical Data and     */
  11. ;*    Computer Software clause at 252.227-7013.            */
  12. ;*    Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138    */
  13. ;************************************************************************/
  14. ;
  15.  
  16. ; Here we define the segments in this module to force their
  17. ; ordering.
  18. ;
  19.  
  20. CODESEG    segment public byte 'CODE'
  21. CODESEG    ends
  22.  
  23. DATASEG    segment public dword 'DATA'
  24. DATASEG    ends
  25.  
  26. ;
  27. ; Global data
  28. ;
  29. DATASEG segment 
  30.  
  31. ebpsave    dd    ?        ; Saved protected mode EBP 
  32. espsave    dd    ?        ; Saved protected mode ESP
  33. sssave    dw    ?        ; Saved protected mode SS
  34.  
  35. ssexit    dw    ?        ; Saved SS for exit
  36. espexit    dd    ?        ; Save ESP for exit
  37.  
  38. exitflag dw    0        ; Exiting from real mode server flag
  39.  
  40. ;
  41. ; EXEC parameter block for EXEC to load real mode server
  42. ;
  43. ldparm    dd    0        ; Environment offset
  44.     dw    0        ; Environment selector
  45.     dd    offset cmdtail    ; Offset of the command tail
  46.     dw    14h        ; Selector of the command tail
  47.  
  48. ;
  49. ; We pass some parameters to the real mode server in the DOS command tail
  50. ;
  51. cmdtail db    12        ; Length of the command tail is 12
  52. callback dd    ?        ; real mode FAR ptr to 386|DOS-X routine to
  53.                 ;    call protected mode
  54.     dd    protret        ; address of "protret" entry point the real
  55.                 ;    mode server calls after it initializes
  56. protcs    dw    ?        ; protected mode CS
  57. protpsp    dw    ?        ; Protected mode program's PSP 
  58.     db    0dh        ; CR to make DOS happy
  59.  
  60. TRUE    equ    1
  61. FALSE    equ    0
  62. fp387f    dd    ?        ; T ==> 387 present, F ==> not present
  63. prot_387state db 108 dup (?)    ; protected mode pgm floating point state
  64.  
  65. ;
  66. ;    Special stack used only during the EXEC call
  67. ;
  68.     align    4
  69.     db    128 dup (?)    
  70. exec_stack label    byte
  71.  
  72. DATASEG    ends
  73.  
  74.     assume    cs:CODESEG,ds:DATASEG
  75.  
  76. CODESEG    segment 
  77.  
  78. ;
  79. ;    realload - Load and initialize a real mode driver
  80. ;
  81. ;    retcode = realload(filenamep, srvptrp, exe_blockp);
  82. ;
  83. ;        int retcode;        /* Return code */
  84. ;        char *filenamep;    /* Pointer to the file name */
  85. ;        REALPTR *srvptrp;    /* returned;  real mode FAR address
  86. ;                       of server interface routine */
  87. ;        EXEC_BLK *exe_blockp;    /* Pointer to parameter block used to 
  88. ;                       load real mode server */ 
  89. ;
  90. ;    This routine loads the real mode server program.
  91. ;    The caller passes in the file name of 
  92. ;    the server to be loaded.  No path searching is done by the routine for
  93. ;    file therefore a complete file path must be given for the file or the
  94. ;    file must be located in the current directory.  If the load is
  95. ;    successful, then the return code is set to zero and the real mode
  96. ;    address in segment:offset format of the server is returned
  97. ;    to the caller.  The server is called by passing this address to
  98. ;    the routine "realcall".  If the load is unsuccesful, then the return
  99. ;    code is set to one of the following MS-DOS error codes:
  100. ;
  101. ;        2 = File not found or invalid path
  102. ;        5 = Access denied
  103. ;        8 = Not enough memory to load program
  104. ;        10 = Invalid environment segment
  105. ;        11 = Invalid file format
  106. ;    
  107.     public    realload    ; Publics for High C/C++
  108.     public    _realload    ; Publics for Microsoft C/C++
  109.     public    realload_    ; Publics for Watcom C/386
  110.  
  111. realload proc    near
  112. _realload:
  113. realload_:
  114. ;
  115. ; Stack frame
  116. ;
  117. #filenamep equ    dword ptr [ebp + 8]    ; File name pointer
  118. #srvptrp equ    dword ptr [ebp + 12]    ; Pointer to returned server address
  119. #exe_blockp equ    dword ptr [ebp + 16]    ; Pointer to EXEC parameter block
  120.  
  121.     push    ebp        ; Set-up a stack frame and save registers
  122.     mov    ebp,esp        ;
  123.     push    ebx        ; 
  124.     push    ecx        ;
  125.     push    edx        ;
  126.     push    edi        ;
  127.     push    esi        ;
  128.     push    es        ;
  129.  
  130. ;
  131. ; If we have a 387 present, save the floating point state so we can restore
  132. ; it again after the real mode program initializes.  (It's not necessary
  133. ; to save the state if there's no coprocessor and we're emulating, since
  134. ; the real mode and prot mode emulators won't interfere with each other.
  135. ; Since we don't unconditionally do an FSAVE/FRSTOR, someone could pick up
  136. ; this glue code and use it with a non-floating-point program without
  137. ; having it break on a machine without a coprocessor).
  138. ;
  139.     mov    fp387f,FALSE    ; assume no coprocessor
  140.     int    11h        ; branch if no coprocessor
  141.     test    eax,2            ;
  142.     jz    short #no_87        ;
  143.     mov    fp387f,TRUE    ; flag coprocessor present
  144.     fsave    prot_387state    ; save current coprocessor state
  145. #no_87:
  146.  
  147. ;
  148. ; Complete the parameter block that we pass to the real mode server in
  149. ; the DOS command tail
  150. ;
  151.     mov    ah,51h        ; protected mode program's PSP
  152.     int    21h        ;    on the stack
  153.     mov    protpsp,bx    ;
  154.  
  155.     mov    protcs,cs    ; Save the CS register for our protected mode
  156.                 ;  return address.  The offset is filled in
  157.                 ;  at link time.
  158.  
  159.     mov    ax,250DH    ; Get the real-to-protected mode
  160.     int    21h        ;    call-back address and save it in our
  161.     mov    callback,eax    ;    parameter block.
  162.  
  163. ;
  164. ; Now EXEC to the real mode program.  Before making the EXEC call, switch
  165. ; to a temporary stack buffer that we use just for the EXEC.  This is
  166. ; because after the real mode server initializes, we will return from
  167. ; this routine and continue using our current stack.  Later on, when
  168. ; we tell the real mode server to terminate, the INT 21h from the EXEC
  169. ; call will return, on the same stack it was on when the INT 21h was made --
  170. ; so if we didn't have a temp stack we'd be stepping on the current stack,
  171. ; which by that time might be in use again (if realexit() is down more
  172. ; levels of function calls than realload() is).
  173. ;
  174.     mov    ebpsave,ebp    ; Save our current EBP and SS:ESP in globals
  175.     mov    espsave,esp    ;
  176.     mov    sssave,ss    ;
  177.  
  178.     mov    edx,#filenamep    ; get filename ptr before switching stacks
  179.  
  180.     lea    esp,exec_stack    ; switch to temp EXEC stack
  181.  
  182.     lea    ebx,ldparm    ; EXEC to the real mode server normally
  183.     mov    ax,ds        ;
  184.     mov    es,ax        ;
  185.     mov    ax,4B00h    ;
  186.     int    21H        ;
  187.  
  188.     jc    #err        ; Branch if a load error.  Error return code
  189.                 ;    is already in EAX
  190.  
  191.     jmp    exitret        ; EXEC returns successfully when the real
  192.                 ;    mode server terminates.  This only
  193.                 ;    occurs when we tell it to terminate
  194.                 ;    by calling the realexit() routine.
  195.                 ;    So jump back into the point in the
  196.                 ;    realexit() routine where it makes the
  197.                 ;    real mode server terminate.
  198.  
  199. ;
  200. ; After the real mode server loads and initializes, it uses the 386|DOS-X
  201. ; service to call through to protected mode to the "protret" label, whose
  202. ; address we passed to the server in the command tail.  The real mode
  203. ; server passes the real mode FAR address of the server function in EAX.
  204. ;
  205. ; When we get here, we are on the real mode server's stack, and the current
  206. ; PSP is the real mode server's PSP.  We want to get back on our own stack,
  207. ; switch back to our own PSP, and return to the caller of realload().
  208. ;
  209. protret:
  210.     
  211.     mov    ssexit,ss    ; Save the current stack for when we
  212.     mov    espexit,esp    ;    want to return to the real mode
  213.                 ;    code in order to force an exit.
  214.  
  215.     mov    ebp,ebpsave    ; Switch back to our regular stack.
  216.     mov    ss,sssave    ;
  217.     mov    esp,espsave    ;
  218.  
  219.     mov    ebx,#srvptrp    ; Return the server function pointer in the
  220.     mov    [ebx],eax    ;     real mode code to the caller.
  221.  
  222.     mov    bx,protpsp    ; Switch back to the protected mode pgm's PSP
  223.     mov    ah,51h        ;
  224.     int    21h        ;
  225.  
  226.     cmp    fp387f,FALSE    ; Restore the prot mode pgm's 387 state
  227.     je    short #no_87_rst
  228.     frstor    prot_387state
  229. #no_87_rst:
  230.  
  231.     sub    eax,eax        ; Zero the return to indicate a successful
  232.                 ;    load.
  233.  
  234. #ret:    pop    es        ; Restore the registers and return
  235.     pop    esi        ;
  236.     pop    edi        ;
  237.     pop    edx        ;
  238.     pop    ecx        ;
  239.     pop    ebx        ;
  240.     pop    ebp        ;
  241.     ret            ;
  242.  
  243. #err:    mov    ebp,ebpsave    ; Switch back to our normal stack
  244.     mov    ss,sssave    ;
  245.     mov    esp,espsave    ;
  246.     jmp    #ret        ; Go return
  247.  
  248. realload endp
  249.  
  250.  
  251. ;
  252. ;    realexit - Force the real mode code to exit
  253. ;
  254. ;    realexit();
  255. ;
  256. ;    The "realexit" routine is called to force the real mode server to
  257. ;    exit.  It must be called by the protected mode code so that the
  258. ;    memory allocated to the real mode code is freed and the real mode
  259. ;    open files are closed.  
  260. ;    
  261.     public    realexit
  262.     public    _realexit
  263.     public    realexit_
  264.  
  265. realexit proc    near
  266. _realexit:
  267. realexit_:
  268.  
  269.     push    ebp        ; Set-up a stack frame.
  270.     mov    ebp,esp        ;
  271.     push    ebx        ;
  272.     push    ecx        ;
  273.     push    edx        ;
  274.     push    edi        ;
  275.     push    esi        ;
  276.     push    es        ;
  277.  
  278.     mov    ebpsave,ebp    ; Save our current EBP and SS:ESP in globals
  279.     mov    espsave,esp    ;
  280.     mov    sssave,ss    ;
  281.  
  282.     mov    exitflag,1    ; Turn on the flag that says we are telling
  283.                 ;    the real mode server to exit.
  284.  
  285. ;
  286. ; Now "tell" the real mode server to exit.
  287. ; We do this by returning from the original call through to protected mode
  288. ; (to label "protret") that the server made way back when it first initialized.
  289. ; To return from that call, all we have to do is switch back to the stack
  290. ; we were on at that point (which we saved in globals), and execute
  291. ; a FAR return instruction.
  292. ;
  293.     mov    ss,ssexit    ; Reload SS:ESP.
  294.     mov    esp,espexit    ;
  295.     db    0cbh        ; Use a far return instruction to go back
  296.                 ;    to the real mode code.
  297.  
  298. ;
  299. ; When the server terminates, it returns from the original INT 21h func 4Bh
  300. ; EXEC that was done in the realload() routine.  That routine then immediately
  301. ; jumps to the "exitret" label below.
  302. ;
  303. ; When we get here, the real mode server and its PSP are gone, and we are
  304. ; back on our own PSP.  However, the stack is the temp EXEC stack that we
  305. ; switched to just before making the original INT 21h func 4Bh call.
  306. ; So we have to switch back to the stack we had when realexit() was called.
  307. ;
  308. exitret:
  309.  
  310. ;
  311. ; If the real mode server exited before we told it to by returning from
  312. ; that initialization time call to "protret" above, then we are hosed,
  313. ; because we have no idea where in the protected mode program we are
  314. ; executing.
  315. ;
  316.     cmp    exitflag,0    ; Branch if the exit flag is off. (oops!)
  317.     je    #err        ;
  318.  
  319.     mov    ebp,ebpsave    ; Switch back to our regular stack.
  320.     mov    ss,sssave    ;
  321.     mov    esp,espsave    ;
  322.  
  323.     mov    exitflag,0    ; Clear the exit flag.
  324.  
  325.     pop    es        ; Restore the registers and return.
  326.     pop    esi        ;
  327.     pop    edi        ;
  328.     pop    edx        ;
  329.     pop    ecx        ;
  330.     pop    ebx        ;
  331.     pop    ebp        ;
  332.     ret            ;
  333.  
  334. #err:    mov    edx,offset #errmsg ;  Output error message "Fatal error:
  335.     push    cs        ;    Unexpected exit from real mode code.".
  336.     pop    ds        ;
  337.     mov    ah,09h        ;
  338.     int    21h        ;
  339.  
  340.     mov    ax,4c01h    ; Exit ourselves.
  341.     int    21h        ;
  342.  
  343. #errmsg    db    'Fatal error: Unexpected exit from real mode code.'
  344.     db    0dh,0ah,'$'
  345.  
  346. realexit endp
  347.  
  348. CODESEG ends
  349.  
  350.     end
  351.