home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c220 / 7.ddi / EXAMPLES / GRAPHICS / PROT.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-02-04  |  14.3 KB  |  577 lines

  1. ;
  2. ;    prot.asm - Protected mode assembler code for gserver
  3. ;
  4. ;************************************************************************/
  5. ;*    Copyright (C) 1986-1988 Phar Lap Software, Inc.            */
  6. ;*    Unpublished - rights reserved under the Copyright Laws of the    */
  7. ;*    United States.  Use, duplication, or disclosure by the         */
  8. ;*    Government is subject to restrictions as set forth in         */
  9. ;*    subparagraph (c)(1)(ii) of the Rights in Technical Data and     */
  10. ;*    Computer Software clause at 252.227-7013.            */
  11. ;*    Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138    */
  12. ;************************************************************************/
  13. ;
  14. ; This code can be built in two ways:  one to use -REALBREAK and the
  15. ; other to use -CALLBUFS.  The -REALBREAK method will yield higher
  16. ; performance but is not DPMI compliant.  The REALBREAK symbol is
  17. ; used to signal that the -REALBREAK method should be used.  If it
  18. ; is not defined, the the -CALLBUFS method is used.
  19. ;
  20. ; To build for -CALLBUFS method:
  21. ;    386asm prot.asm -nolist
  22. ;
  23. ; To build for -REALBREAK method:
  24. ;    386asm prot.asm -DREALBREAK -nolist
  25. ;
  26.  
  27. ; Here we define the segments in this module to force their
  28. ; ordering.
  29. ;
  30. ; We need the real mode communications segment if we are going to
  31. ; use the -REALBREAK method.  Otherwise we will use the buffer
  32. ; allocated with the -CALLBUFS switch for communication.
  33. ;
  34. IFDEF REALBREAK
  35. commseg    segment public byte 'realcomm'
  36. commseg    ends
  37. ENDIF
  38.  
  39. codeseg    segment public byte 'code'
  40. codeseg    ends
  41.  
  42. dataseg    segment public byte 'data'
  43. dataseg    ends
  44.  
  45. ;
  46. ; Set up the dgroup appropriately
  47. ;
  48. IFDEF REALBREAK
  49. dgroup    group    commseg,dataseg
  50. ELSE
  51. dgroup    group    dataseg
  52. ENDIF
  53.  
  54.     assume    cs:codeseg,ds:dgroup,ss:dgroup,es:dgroup
  55.  
  56. ;
  57. ; Export the names for the graphics buffer pointer and
  58. ; size variables.
  59. ;
  60.     public    _gbuffsize,_gbuffp
  61.     public    __gbuffsize,__gbuffp
  62.  
  63. ;
  64. ; Define the real mode communications segment and its variables
  65. ; if we are going to use the -REALBREAK method.
  66. IFDEF REALBREAK
  67.  
  68.     public _realend
  69.  
  70. commseg    segment public byte 'realcomm'
  71.  
  72. buffsize    equ    4096
  73.  
  74. __gbuffsize:
  75. _gbuffsize    dd     buffsize
  76. __gbuffp:
  77. _gbuffp        dd    _gbuff
  78. _gbuff        db    buffsize dup (?)
  79.  
  80. _realend    equ    $
  81.  
  82. commseg    ends
  83.  
  84. ENDIF
  85.  
  86. codeseg    segment public byte 'code'
  87.  
  88. ;
  89. ;    realload - Load and initialize a real mode driver
  90. ;
  91. ;    retcode = realload(filenameptr, &realptr);
  92. ;
  93. ;        int retcode;        /* Return code */
  94. ;        char *filenameptr;    /* Pointer to the file name */
  95. ;        unsigned long *realptr;    /* Segment:offset address of server */
  96. ;
  97. ;    This routine loads a real mode server and calls the initialization
  98. ;    routine for the server.  The caller passes in the file name of 
  99. ;    the server to be loaded.  No path searching is done by the routine for
  100. ;    file therefore a complete file path must be given for the file or the
  101. ;    file must be located in the current directory.  If the load is
  102. ;    successful, then the return code is set to zero and the real mode
  103. ;    address in segment:offset format of the server is returned
  104. ;    to the caller.  The server is called by passing this address to
  105. ;    the routine "realcall".  If the load is unsuccesful, then the return
  106. ;    code is set to one of the following MS-DOS error codes:
  107. ;
  108. ;        2 = File not found or invalid path
  109. ;        5 = Access denied
  110. ;        8 = Not enough memory to load program
  111. ;        10 = Invalid environment segment
  112. ;        11 = Invalid file format
  113. ;    
  114.  
  115.     public    realload,protret    ; Publics for High-C 
  116.     public    _realload,_protret    ; Publics for NDP-C 
  117.  
  118. realload proc    near
  119. _realload:
  120.  
  121.  
  122. ;    EQU's for the argument list
  123.  
  124. #filenamep equ    dword ptr [ebp + 8]    ; File name pointer
  125. #srvptrp equ    dword ptr [ebp + 12]    ; Pointer to returned server address
  126.  
  127. ;    Function prologue
  128.  
  129.     push    ebp        ; Set-up a stack frame and save registers.
  130.     mov    ebp,esp        ;
  131.     push    ebx        ;
  132.     push    ecx        ;
  133.     push    edx        ;
  134.     push    edi        ;
  135.     push    esi        ;
  136.     push    es        ;
  137.  
  138. ;    Build up the parameter block for the real mode code that contains
  139. ;    (1) the address of the DOS-Extender routine that switches from real
  140. ;    mode back to protected mode, (2) the protected mode return address,
  141. ;    and (3) the segment pointer to the protected mode PSP.  This 
  142. ;    parameter block is passed to the real mode server as a command
  143. ;    tail in the PSP. 
  144.  
  145.     sub    ebx,ebx        ; Convert the address of the protected
  146.     mov    ax,4h        ;    mode PSP from a protected mode selector
  147.     mov    es,ax        ;    to a real mode segment pointer. 
  148.     sub    ecx,ecx        ;
  149.     mov    ax,250Fh    ;    
  150.     int    21h        ;
  151.  
  152.     push    ecx        ; Save it in our parameter block for use
  153.     pop    cx        ;    by the real mode code.
  154.     pop    cx        ;
  155.     mov    protpsp,cx    ;
  156.  
  157.     mov    protcs,cs    ; Save the CS register for our protected mode
  158.                 ;  return address.  The offset is filled in
  159.                 ;  at link time.
  160.  
  161.     mov    ax,250DH    ; Get the real-to-protected mode
  162.     int    21h        ;    call-back address and save it in our
  163.     mov    callback,eax    ;    parameter block.
  164.  
  165. ;
  166. ; If we are using the -CALLBUFS method, then we will set up the _gbuffp
  167. ; and _gbuffsize variables to point at and contain the size of the
  168. ; intermode call buffer.  We will be using this buffer as the real mode
  169. ; communications buffer.  The far pointer to the buffer came back in es:edx
  170. ; after the 250D call.  We will also make sure that the buffer is at least
  171. ; 1Kb in size.  If it is too small, we will return an insufficient memory
  172. ; error.
  173. ;
  174. IFNDEF REALBREAK
  175.     cmp    ecx,1024    ; Is the buffer big enough?
  176.     jge    #l10        ; Yes, go set up pointer and size variables.
  177.     mov    eax,8        ; No, load insufficient memory error code
  178.     jmp    #ret        ;  and branch to return it.
  179. #l10:
  180.     lea    esi,_gbuffp    ; Get a pointer to the far pointer
  181.     mov    [esi],edx    ; Store the offset portion of the pointer
  182.     mov    [esi+4],es    ;  and then the segment portion of the pointer
  183.     mov    _gbuffsize,ecx    ; Store the size of the bugger.
  184. ENDIF
  185.  
  186. ;    We now switch to a special stack for the EXEC system call because
  187. ;    the stack will be re-used in strange ways when we exit from the
  188. ;    real mode code and it will conflict with the regular stack.
  189.  
  190.     mov    ebpsave,ebp    ; Save EBP and SS:ESP.
  191.     mov    espsave,esp    ;
  192.     mov    sssave,ss    ;
  193.  
  194.     mov    edx,#filenamep    ; Load the file name pointer into EDX
  195.                 ;    while we still have the caller's
  196.                 ;    stack.
  197.  
  198.     mov    esp,offset endxstack    ; Switch to the EXEC stack.
  199.  
  200. ;    Load the real mode server and execute its initialization code.
  201. ;    We use the special EXEC system call (25C3) instead of system
  202. ;    call 4B so that the DOS-Extender run-time environment is not
  203. ;    disturbed.
  204.  
  205.     mov    ebx,offset ldparm ; EXEC to the real mode program.
  206.     push    ds        ;
  207.     pop    es        ;
  208.     mov    ax,25C3H    ;
  209.     int    21H        ;
  210.  
  211.     jc    #err        ; Branch if a load error.
  212.  
  213.     jmp    exitret        ; If EXEC returns it must be an exit
  214.                 ;    from the real mode code.  Therefore
  215.                 ;    go to the exit routine.
  216.  
  217. ;    If everything went okay, we get control back to the label
  218. ;    "protret" from the real mode initialization routine.  
  219.  
  220. protret:
  221. _protret:
  222.     
  223.     mov    ssexit,ss    ; Save the current stack for when we
  224.     mov    espexit,esp    ;    want to return to the real mode
  225.                 ;    code in order to force an exit.
  226.  
  227.     mov    ebp,ebpsave    ; Switch back to our regular stack.
  228.     mov    ss,sssave    ;
  229.     mov    esp,espsave    ;
  230.  
  231.     mov    ebx,#srvptrp    ; Return the server pointer to the caller.
  232.     mov    [ebx],eax    ;
  233.  
  234.     call    psprest        ; Restore the protected mode PSP.
  235.  
  236.     sub    eax,eax        ; Zero the return to indicate a successful
  237.                 ;    load.
  238.  
  239. #ret:    pop    es        ; Restore the registers and return.
  240.     pop    esi        ;
  241.     pop    edi        ;
  242.     pop    edx        ;
  243.     pop    ecx        ;
  244.     pop    ebx        ;
  245.     pop    ebp        ;
  246.     ret            ;
  247.  
  248. ;    Error exit code
  249.  
  250. #err:    mov    ebp,ebpsave    ; Switch back to our regular stack.
  251.     mov    ss,sssave    ;
  252.     mov    esp,espsave    ;
  253.  
  254.     jmp    #ret        ; Go return.
  255.  
  256. realload endp
  257.  
  258.  
  259. ;
  260. ;    realcall - Call a real mode procedure and pass in a single far
  261. ;           pointer argument
  262. ;
  263. ;    retcode = realcall(funcptr, dataptr);
  264. ;
  265. ;        int retcode;        /* Return code */
  266. ;        unsigned long funcptr;    /* Segment:offset address of function */        
  267. ;        unsigned long dataptr;    /* Segment:offset address of data */
  268. ;    
  269. ;    This function is used to call a real mode function from protected
  270. ;    mode.  The caller passes in the real mode address in segment:offset
  271. ;    format of the real mode function to be called as well as a single
  272. ;    real mode address to a data block to be passed to the real mode
  273. ;    function.  The return code from the routine is the contents of the
  274. ;    EAX register that the real mode function exits with.
  275. ;
  276.  
  277.     public    realcall        ; Public for High-C 
  278.     public    _realcall        ; Public for NDP-C 
  279.  
  280. realcall proc    near
  281. _realcall:
  282.  
  283. ;    Argument list EQU's
  284.  
  285. #funcptr equ    dword ptr [ebp + 8]
  286. #farptr     equ    dword ptr [ebp + 12]
  287.  
  288. ;    This routine calls the real mode function using
  289. ;    system call number 250E.
  290.  
  291.     push    ebp        ; Set-up a stack frame.
  292.     mov    ebp,esp        ;
  293.     push    ebx        ;
  294.     push    ecx        ;
  295.     push    edx        ;
  296.     push    edi        ;
  297.     push    esi        ;
  298.  
  299.     push    #farptr        ; Call the real mode procedure.
  300.     mov    ebx,#funcptr    ;
  301.     mov    ecx,2        ;
  302.     mov    ax,250eh    ;
  303.     int    21h        ;
  304.  
  305.     add    esp,4        ; Clean up the stack.
  306.  
  307.     pop    esi        ; Restore the registers.
  308.     pop    edi        ;
  309.     pop    edx        ;
  310.     pop    ecx        ;
  311.     pop    ebx        ;
  312.     pop    ebp        ;
  313.  
  314.     ret            ; Return.
  315.  
  316. realcall endp
  317.  
  318.  
  319. ;
  320. ;    realexit - Force the real mode code to exit
  321. ;
  322. ;    realexit();
  323. ;
  324. ;    The "realexit" routine is called to force the real mode server to
  325. ;    exit.  It must be called by the protected mode code so that the
  326. ;    memory allocated to the real mode code is freed and the real mode
  327. ;    open files are closed.  The routine is implemented by returning
  328. ;    to the real mode code to the point when it did a call back after
  329. ;    the EXEC system call.
  330. ;    
  331.  
  332.     public    realexit
  333.     public    _realexit
  334.  
  335. realexit proc    near
  336. _realexit:
  337.  
  338. ;    Argument list EQU's
  339.  
  340. #funcptr equ    dword ptr [ebp + 8]
  341.  
  342. ;    Function prologue
  343.  
  344.     push    ebp        ; Set-up a stack frame.
  345.     mov    ebp,esp        ;
  346.     push    ebx        ;
  347.     push    ecx        ;
  348.     push    edx        ;
  349.     push    edi        ;
  350.     push    esi        ;
  351.     push    es        ;
  352.  
  353.  
  354. ;    Save the stack pointer
  355.  
  356.     mov    ebpsave,ebp    ; Save EBP and SS:ESP.
  357.     mov    espsave,esp    ;
  358.     mov    sssave,ss    ;
  359.  
  360.  
  361. ;    Switch back to the stack that we had when we returned from EXEC
  362.  
  363.     mov    ss,ssexit    ; Reload SS:ESP.
  364.     mov    esp,espexit    ;
  365.  
  366. ;    Turn on the real mode exit flag
  367.  
  368.     mov    exitflag,1    ;
  369.  
  370. ;    Return back to the real mode code which will then do an exit
  371.  
  372.     db    0cbh        ; Use a far return instruction to go back
  373.                 ;    to the real mode code.
  374.  
  375.  
  376. ;    Switch back to the standard protected mode stack and return.
  377.  
  378. exitret:
  379.  
  380.     cmp    exitflag,0    ; Branch if the exit flag is off. (oops!)
  381.     je    #err        ;
  382.  
  383.     mov    exitflag,0    ; Clear the exit flag.
  384.  
  385.     mov    ebp,ebpsave    ; Switch back to our regular stack.
  386.     mov    ss,sssave    ;
  387.     mov    esp,espsave    ;
  388.  
  389.     call    psprest        ; Restore the protected mode PSP.
  390.  
  391.     pop    es        ; Restore the registers and return.
  392.     pop    esi        ;
  393.     pop    edi        ;
  394.     pop    edx        ;
  395.     pop    ecx        ;
  396.     pop    ebx        ;
  397.     pop    ebp        ;
  398.     ret            ;
  399.  
  400. #err:    mov    edx,offset #errmsg ;  Output error message "Fatal error:
  401.     push    cs        ;    Unexpected exit from real mode code.".
  402.     pop    ds        ;
  403.     mov    ah,09h        ;
  404.     int    21h        ;
  405.  
  406.     mov    ax,4c01h    ; Exit ourselves.
  407.     int    21h        ;
  408.  
  409. #errmsg    db    'Fatal error: Unexpected exit from real mode code.'
  410.     db    0dh,0ah,'$'
  411.  
  412. realexit endp
  413.  
  414.  
  415. ;
  416. ;    prottoreal - Convert a protected mode address to a real mode address
  417. ;
  418. ;    realptr = prottoreal(offset32, selector);
  419. ;
  420. ;        unsigned long realptr;    /* Segment:offset real mode address */
  421. ;        unsigned long offset32;    /* Protected mode offset */
  422. ;        unsigned short selector;/* Protected mode selector */
  423. ;
  424. ;    This routine converts a 48-bit protected mode pointer (selector +
  425. ;    32-bit offset) to the equivalent segment:offset real mode address.
  426. ;    If the protected mode address maps to a memory location outside of
  427. ;    the first 1-megabyte of the real mode address space, then a NULL
  428. ;    pointer is returned.
  429. ;
  430.     
  431.     public    prottoreal
  432.     public    _prottoreal
  433.  
  434. prottoreal proc    near
  435. _prottoreal:
  436.  
  437. ;    Argument list EQU's
  438.  
  439. #offset    equ    dword ptr [ebp + 8]
  440. #sel    equ    word ptr [ebp + 12]
  441.  
  442. ;    System call 250F does all of the work for us
  443.  
  444.     push    ebp        ; Save all of the registers
  445.     mov    ebp,esp        ;
  446.     push    ebx        ;
  447.     push    ecx        ;
  448.     push    es        ;
  449.  
  450.     mov    ebx,#offset    ; Do the conversion.
  451.     mov    es,#sel        ;
  452.     sub    ecx,ecx        ;
  453.     mov    ax,250fh    ;    
  454.     int    21h        ;
  455.  
  456.     jnc    #skip        ; If there is an error, return a null
  457.     sub    ecx,ecx        ;    pointer.
  458.  
  459. #skip:    mov    eax,ecx        ; Load the final real pointer into EAX.
  460.  
  461.     pop    es        ; Clean up.
  462.     pop    ecx        ;
  463.     pop    ebx        ;
  464.     pop    ebp        ;
  465.  
  466.     ret            ; Return.
  467.  
  468. prottoreal endp
  469.  
  470.  
  471. ;
  472. ;    psprest - Restore the protected mode PSP
  473. ;
  474. ;    This routine is only used internally by this module.
  475. ;    
  476.  
  477. psprest    proc    near        ;
  478.  
  479.     push    ebx        ; Save registers.
  480.     push    es        ;
  481.  
  482.     mov    bx,protpsp    ; Switch back to the protected mode PSP.
  483.     mov    ah,50h        ;
  484.     int    21h        ;
  485.     
  486.     pop    es        ; Restore registers.
  487.     pop    ebx        ;
  488.  
  489.     ret            ; Return.
  490.  
  491. psprest    endp
  492.  
  493. codeseg    ends
  494.  
  495. ;
  496. ;    The data segment
  497. ;
  498.  
  499. dataseg    segment public byte 'data'
  500.  
  501. IFNDEF REALBREAK
  502. ;
  503. ; If we are using the -CALLBUFS method, then we will put the
  504. ; far pointer to the intermode call buffer and its size here.
  505. ;
  506. __gbuffsize:
  507. _gbuffsize    dd     ?
  508. __gbuffp:
  509. _gbuffp        dp    ?
  510. ENDIF
  511.  
  512. ;
  513. ;    ldparm - Parameter block using by the EXEC system call to
  514. ;             load the real mode server
  515. ;
  516.  
  517. ldparm    dd    0        ; Environment offset
  518.     dw    0        ; Environment selector
  519.     dd    offset cmdtail    ; Offset of the command tail
  520.     dw    14h        ; Selector of the command tail
  521.  
  522.  
  523. ;
  524. ;    The parameter block passed to the real mode code as a fake
  525. ;    command tail.  The format of the parameter block is:
  526. ;
  527. ;        word 0 - Offset of the 386|DOS-Extender routine that
  528. ;                 the real mode server calls to switch back
  529. ;                 to protected mode
  530. ;        word 2 - Segment of the 386|DOS-Extender routine that
  531. ;                 the real mode code calls to switch back
  532. ;                 to protected mode
  533. ;        dword 4 - 32-bit protected mode offset that the real
  534. ;                  mode code is to return to when it completes
  535. ;              its initialization 
  536. ;        word 8 - Real segment pointer to the PSP of the protected
  537. ;                 mode code
  538. ;
  539.  
  540. cmdtail db    12        ; Length of the command tail is 12
  541. callback dd    ?        ; First address is call back address
  542.     dd    protret        ; Second address is the return address
  543. protcs    dw    ?
  544. protpsp    dw    ?        ; Protected mode PSP segment pointer
  545.     db    0dh        ; CR to make DOS happy
  546.  
  547. ;
  548. ;    Saved registers
  549. ;
  550.  
  551. ebpsave    dd    ?        ; Saved protected mode EBP 
  552. espsave    dd    ?        ; Saved protected mode ESP
  553. sssave    dw    ?        ; Saved protected mode SS
  554.  
  555. ssexit    dw    ?        ; Saved SS for exit
  556. espexit    dd    ?        ; Save ESP for exit
  557.  
  558. ;
  559. ;    Special stack used only during the EXEC call
  560. ;
  561.  
  562. xstack    db    512 dup (?)    ;
  563. endxstack label    byte
  564.  
  565.  
  566. ;
  567. ;    Misc. variables
  568. ;
  569.  
  570. exitflag db    0        ; Exiting from real mode server flag
  571.  
  572. dataseg    ends
  573.  
  574.     end
  575.