home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / b / bc3.zip / DPMI.ASM < prev    next >
Assembly Source File  |  1992-02-17  |  69KB  |  2,845 lines

  1.  
  2. ;;  Copyright (c) 1992, Qualitas, Inc.  All Rights Reserved
  3. ;;
  4. ;;  dpmi.asm - Source code for Qualitas DPMI library
  5. ;;
  6.  
  7.     include dpmi.inc
  8.  
  9.     .286p
  10.     .model SMALL, C
  11.  
  12.     .data
  13.  
  14. ;; data required by fix-up routines
  15.  
  16. codePara    dw    ?    
  17. dataPara    dw    ?    
  18. fixupSel    dw    ?
  19. previous21    dd    ?
  20.  
  21.     .code
  22.  
  23. ;;======================================================================
  24. ;; Function: Release Time Slice
  25. ;;
  26. ;; Synopsis:
  27. ;;
  28. ;;    void DPMIReleaseTimeSlice(void);
  29. ;;
  30. ;; Description:
  31. ;;
  32. ;;    DPMI clients call this function to indicate an idle state to the
  33. ;;    DPMI host.  This enables multitasking DPMI hosts to schedule other
  34. ;;    clients. Installing this call inside idle loops can result in 
  35. ;;    significant improvement of system throughput.
  36. ;;
  37. ;; DPMI reference: INT 2Fh AX=1680h
  38.  
  39. DPMIReleaseTimeSlice PROC C 
  40.     mov    ax, 1680h
  41.     int    2fh
  42.     ret
  43. DPMIReleaseTimeSlice ENDP
  44.  
  45. ;;======================================================================
  46. ;; Function: Get CPU Mode
  47. ;;
  48. ;; Synopsis:
  49. ;;
  50. ;;    int DPMIGetCPUMode(void);
  51. ;;
  52. ;; Description:
  53. ;;
  54. ;;    This function may be used by mode sensitive applications to determine
  55. ;;    the current processor operating mode. Clients must verify the 
  56. ;;    presence of a DPMI host prior to making this call. The function
  57. ;;    returns zero if executing in protected mode, and returns non-zero
  58. ;;    if running in real or virtual 86 mode.
  59. ;;    
  60. ;; DPMI reference: INT 2Fh AX=1686h
  61.  
  62. DPMIGetCPUMode PROC C
  63.     mov    ax, 1686h
  64.     int    2Fh
  65.     ret
  66. DPMIGetCPUMode ENDP
  67.  
  68. ;;======================================================================
  69. ;; Function: Obtain Mode Switch Entry Point
  70. ;;
  71. ;; Synopsis:
  72. ;;
  73. ;;    int DPMIObtainSwitchEntryPoint(
  74. ;;        uShort *flags,            ;; 32-bitness flag
  75. ;;        uChar *processor,        ;; processor type
  76. ;;        uChar *majorVersion,        ;; major version #
  77. ;;        uChar *minorVersion,        ;; minor version #
  78. ;;        uShort *nPrivateDataParas,    ;; size of host data
  79. ;;        void (far* *entryAddress)());    ;; switch entry point
  80. ;;        
  81. ;; Description:
  82. ;;
  83. ;;    This call determines if a DPMI host is present, and if so, returns
  84. ;;    necessary information on how to invoke it.  The function returns
  85. ;;    zero if a DPMI host was found; otherwise it returns non-zero.
  86. ;;
  87. ;;    All arguments are pointers to locations to store return values.
  88. ;;    The flags argument is non-zero if the DPMI host supports 32-bit
  89. ;;    applications.  The processor argument is written as 2 (80286),
  90. ;;    3 (80386), 4 (80486), or 5 (future). The version arguments indicate
  91. ;;    the version numbers of the DPMI host (For DPMI 0.9, major version is
  92. ;;    zero, and minor version is 90).  The nPrivateDataParas argument
  93. ;;    receives the number of paragraphs of memory that the host requires
  94. ;;    for each client.  If this is non-zero, the client must provide
  95. ;;    this much memory prior to calling the mode switch entry point, and
  96. ;;    the memory must be paragraph aligned.
  97. ;;
  98. ;;    The value written at the entryAddress argument is the far address 
  99. ;;    to call to make the initial switch into protected mode. See also,
  100. ;;    DPMIEnterProtectedMode.
  101. ;;
  102. ;; DPMI reference: INT 2Fh AX=1687h
  103.  
  104. DPMIObtainSwitchEntryPoint PROC C USES SI DI,    \
  105.     flags:PTR,        \
  106.     processor:PTR,        \
  107.     majorVersion:PTR,    \
  108.     minorVersion:PTR,    \
  109.     nPrivateDataParas:PTR,    \
  110.     entryAddress:PTR
  111.  
  112.     mov    ax, 1687h        ; test for presence of DPMI host
  113.     int    2Fh
  114.  
  115.     or    ax, ax            ; ax == 0 means host responded
  116.     jnz    noHost
  117.  
  118.     mov    ax, bx            ; save flags in ax
  119.  
  120.     ldptr    bx, flags
  121.     mov    [bx], ax
  122.     ldptr    bx, processor
  123.     mov    [bx], cl
  124.     ldptr    bx, majorVersion
  125.     mov    [bx], dh
  126.     ldptr    bx, minorVersion
  127.     mov    [bx], dl
  128.     ldptr    bx, nPrivateDataParas
  129.     mov    [bx], si
  130.     ldptr    bx, entryAddress
  131.     mov    [bx], di
  132.     mov    [bx+2], es
  133.  
  134.     xor    ax, ax    
  135. noHost:
  136.     ret
  137. DPMIObtainSwitchEntryPoint ENDP
  138.  
  139. ;;======================================================================
  140. ;; Function: Enter Protected Mode
  141. ;;
  142. ;; Synopsis:
  143. ;;
  144. ;;    int DPMIEnterProtectedMode(
  145. ;;        void (far *switchEntryPoint)(),    ;; mode switch entry point
  146. ;;        uShort bitness,            ;; 16 or 32
  147. ;;        uShort nPrivateDataParas);    ;; number of paras required
  148. ;;            
  149. ;;
  150. ;; Description:
  151. ;;
  152. ;;    This function is used to make the initial switch into protected
  153. ;;    mode.  The switchEntryPoint argument is the value returned in the
  154. ;;    entryAddress argument of ObtainSwitchEntryPoint.  The bitness argument
  155. ;;    is zero to indicate that the calling client is 16-bit, and is one to 
  156. ;;    indicate that the calling client is 32-bit.  The nPrivateDataParas 
  157. ;;    argument is obtained from the function DPMIObtainSwitchEntryPoint.
  158. ;;
  159. ;;    If the call returns zero, the client is then running in protected
  160. ;;    mode.  The segment registers CS, DS, and SS contain selectors that
  161. ;;    address the same linear memory as they did in real mode at the 
  162. ;;    time of the call.  The selector in ES addresses the programs PSP,
  163. ;;    and the corresponding descriptor has a limit of 0xFF.  If running
  164. ;;    on a 32-bit processor, FS and GS are zero.
  165. ;;
  166. ;; DPMI reference: calling the mode switch entry point
  167. ;;
  168. ;; Version 1.0 Error returns:
  169. ;;
  170. ;;    8011h    descriptor unavailable
  171. ;;    8021h    32-bit clients not supported
  172.  
  173. DPMIEnterProtectedMode PROC C \
  174.     switchEntryPoint:FAR PTR,    \
  175.     bitness:uShort,            \
  176.     nPrivateDataParas:uShort
  177.  
  178.     mov    ah, 48h            ;; get the required memory block
  179.     mov    bx, nPrivateDataParas
  180.     int    21h
  181.     jc    @@fail
  182.  
  183.     mov    es, ax            ;; set up and call the mode switch
  184.     mov    ax, bitness        ;;   entry point to make the initial
  185.     call    switchEntryPoint    ;;   switch into protected mode
  186.     jc    @@fail
  187.     
  188.     call    _fixup            ;; re fixup this exe 
  189.     call    _installHandlers    ;; install default exception handlers
  190.     xor    ax, ax
  191.     jmp    short @@exit
  192. @@fail:
  193.     mov    ax, 1
  194. @@exit:
  195.     ret
  196. DPMIEnterProtectedMode ENDP
  197.  
  198. ;;======================================================================
  199. ;; Function: Allocate Descriptors 
  200. ;;
  201. ;; Synopsis:
  202. ;;
  203. ;;    int DPMIAllocateDescriptors(
  204. ;;        uShort howMany,        ;; how many descriptors to allocate
  205. ;;        selector_t *baseSel);    ;; receives selector of first desc
  206. ;;            
  207. ;; Description:
  208. ;;
  209. ;;    This function allocates one or more LDT descriptors. The howMany
  210. ;;    argument is the number of descriptors to allocate, and the 
  211. ;;    selector of the first allocated descriptor is written to the
  212. ;;    address pointed to by the baseSel argument.  When more than one
  213. ;;    descriptor  is allocated, they are consecutive, i.e., the 
  214. ;;    difference between them is obtained by calling DPMIGetSelectorDelta.
  215. ;;
  216. ;;    At the time of allocation, each descriptor is of type DATA with
  217. ;;    a base and limit of zero.  It is the client's responsibility to
  218. ;;    set up the descriptors with meaningful values.
  219. ;;
  220. ;; DPMI reference: INT 31h AX=0000h
  221. ;;
  222. ;; Version 1.0 Error returns:
  223. ;;
  224. ;;    8011h    descriptor unavailable.
  225.  
  226. DPMIAllocateDescriptors PROC C    \
  227.     howMany:uShort,        \
  228.     baseSel:PTR
  229.  
  230.     mov    ax, 0000h
  231.     mov    cx, howMany
  232.     int    31h
  233.     jc    @@fail
  234.     
  235.     ldptr    bx, baseSel
  236.     mov    [bx], ax
  237.     xor    ax, ax
  238.     jmp    short @@exit
  239. @@fail:
  240.     mov    ax, 1
  241. @@exit:    
  242.     ret
  243. DPMIAllocateDescriptors ENDP
  244.  
  245. ;;======================================================================
  246. ;; Function: Free Descriptor
  247. ;;
  248. ;; Synopsis:
  249. ;;
  250. ;;    int DPMIFreeDescriptor(
  251. ;;        selector_t sel);    ;; Selector of descriptor to free
  252. ;;
  253. ;; Description:
  254. ;;
  255. ;;    This function returns the specified descriptor to the DPMI host.
  256. ;;    
  257. ;; DPMI reference: INT 31h AX=0001h
  258. ;;
  259. ;; Version 1.0 Error returns:
  260. ;;
  261. ;;    8022h    invalid selector
  262.  
  263. DPMIFreeDescriptor PROC C    \
  264.     sel:selector_t
  265.     
  266.     mov    ax, 0001h
  267.     mov    bx, sel
  268.     int    31h
  269.     jc    @@exit
  270.  
  271.     xor    ax, ax
  272. @@exit:
  273.     ret
  274. DPMIFreeDescriptor ENDP
  275.  
  276. ;;======================================================================
  277. ;; Function: Create Descriptor to Address Real Segment
  278. ;;
  279. ;; Synopsis:
  280. ;;
  281. ;;    int DPMIParaToSelector(
  282. ;;        uShort para,        ;; paragraph to map
  283. ;;        selector_t *sel);    ;; selector to address paragraph
  284. ;;    
  285. ;; Description:
  286. ;;
  287. ;;    This function creates a data descriptor whose base corresponds
  288. ;;    to the real mode paragraph specified by the para argument.  The
  289. ;;    function writes the selector of the created descriptor at the
  290. ;;    address pointed to by the sel argument.  The descriptor limit 
  291. ;;    is 64 KB.
  292. ;;
  293. ;;    The function is intended to be used only for commonly accessed
  294. ;;    regions of the low megabyte, for example, paragraphs 40h, A000h,
  295. ;;    and B800h. Descriptors allocated by this function should not be
  296. ;;    modified or freed.  Multiple calls to this function with the same
  297. ;;    input return the same selector.
  298. ;;
  299. ;; DPMI reference: INT 31h AX=0002h
  300. ;;
  301. ;; Version 1.0 Error returns: 
  302. ;;
  303. ;;    8011h    descriptor unavailable
  304.  
  305. DPMIParaToSelector PROC C    \
  306.     para:uShort,        \
  307.     sel:PTR
  308.  
  309.     mov    ax, 0002h
  310.     mov    bx, para
  311.     int    31h
  312.     jc    @@exit
  313.  
  314.     ldptr    bx, sel
  315.     mov    [bx], ax
  316.     xor    ax, ax
  317. @@exit:
  318.     ret
  319. DPMIParaToSelector ENDP
  320.  
  321. ;;======================================================================
  322. ;; Function: Get Selector Delta
  323. ;;
  324. ;; Synopsis:
  325. ;;
  326. ;;    uShort DPMIGetSelectorDelta(void);
  327. ;;    
  328. ;; Description:
  329. ;;
  330. ;;    The return value of this function is the difference between
  331. ;;    consecutive selectors.
  332. ;;
  333. ;; DPMI reference: INT 31h AX=0003h
  334.  
  335. DPMIGetSelectorDelta PROC C
  336.     mov    ax, 0003h
  337.     int    31h
  338.     ret
  339. DPMIGetSelectorDelta ENDP
  340.  
  341. ;;======================================================================
  342. ;; Function: Get Segment Base
  343. ;;
  344. ;; Synopsis:
  345. ;;
  346. ;;    int DPMIGetSegmentBase(
  347. ;;        selector_t sel,        ;; selector of segment to get base of
  348. ;;        uLong *base);        ;; location to receive base of segment
  349. ;;
  350. ;; Description:
  351. ;;
  352. ;;    This function retrieves the base of the segment specified by the
  353. ;;    sel argument.  The linear base of the segment is written at the
  354. ;;    address pointed to by the base argument.
  355. ;;
  356. ;; DPMI reference: INT 31h AX=0006h
  357. ;;
  358. ;; Version 1.0 Error returns:
  359. ;;
  360. ;;    8022h    invalid selector
  361.  
  362. DPMIGetSegmentBase PROC C    \
  363.     sel:selector_t,        \
  364.     base:PTR
  365.  
  366.     mov    ax, 0006h
  367.     mov    bx, sel
  368.     int    31h
  369.     jc    @@exit
  370.     
  371.     ldptr    bx, base
  372.     stlong    [bx], cx, dx
  373.  
  374.     xor    ax, ax
  375. @@exit:
  376.     ret
  377. DPMIGetSegmentBase ENDP
  378.  
  379. ;;======================================================================
  380. ;; Function: Set Segment Base
  381. ;;
  382. ;; Synopsis:
  383. ;;
  384. ;;    int DPMISetSegmentBase(
  385. ;;        selector_t sel,        ;; selector of segment to set base of
  386. ;;        uLong base);        ;; new value for base
  387. ;;
  388. ;; Description:
  389. ;;
  390. ;;    This function sets the base of the segment specified by the sel
  391. ;;    argument to the value of the base argument.
  392. ;;
  393. ;; DPMI reference: INT 31h AX=0007h
  394. ;;
  395. ;; Version 1.0 Error returns:
  396. ;;
  397. ;;    8022h    invalid selector
  398. ;;    8025h    invalid linear address
  399.  
  400. DPMISetSegmentBase PROC C    \
  401.     sel:selector_t,        \
  402.     base:uLong
  403.  
  404.     mov    ax, 0007h
  405.     mov    bx, sel
  406.     ldlong    cx, dx, base
  407.     int    31h
  408.     jc    @@exit
  409.  
  410.     xor    ax, ax
  411. @@exit:
  412.     ret
  413. DPMISetSegmentBase ENDP
  414.  
  415. ;;======================================================================
  416. ;; Function: Get Segment Limit
  417. ;;
  418. ;; Synopsis:
  419. ;;
  420. ;;    int DPMIGetSegmentLimit(
  421. ;;        selector_t sel,        ;; selector of segment to get limit of
  422. ;;        uLong *limit);        ;; location to receive limit
  423. ;;
  424. ;; Description:
  425. ;;
  426. ;;    This function retrieves retrieves the limit of the segment 
  427. ;;    specified by the sel argument, and writes it at the address
  428. ;;    pointed to by the limit argument.  The function is implemented
  429. ;;    not by a DPMI call, but with the LSL instruction.
  430. ;;
  431. ;;
  432. ;; DPMI reference: Not a true DPMI function, but included for completeness.
  433. ;;
  434.  
  435. DPMIGetSegmentLimit PROC C    \
  436.     sel:selector_t,        \
  437.     limit:PTR
  438.  
  439.     mov    ax, 0400h    ;; check processor type
  440.     int    31h
  441.     cmp    cl, 2        ;; 2 means 286
  442.     je    @@is286
  443. .386p
  444.     movzx    eax, sel
  445.     lsl    eax, eax
  446.     jnz    @@fail
  447.     ldptr    bx, limit
  448.     mov    [bx], eax
  449.     xor    ax, ax
  450.     jmp    short @@exit
  451. .286p
  452. @@is286:
  453.     mov    ax, sel
  454.     lsl    ax, ax        ;; get segment limit
  455.     jnz    @@fail        ;; zf=0 if cannot access
  456.  
  457.     ldptr    bx, limit
  458.     stlong    [bx], 0, ax
  459.     xor    ax, ax
  460.     jmp    short @@exit
  461. @@fail:
  462.     mov    ax, 1
  463. @@exit:
  464.     ret
  465. DPMIGetSegmentLimit ENDP
  466.  
  467. ;;======================================================================
  468. ;; Function: Set Segment Limit
  469. ;;
  470. ;; Synopsis:
  471. ;;
  472. ;;    int DPMISetSegmentLimit(
  473. ;;        selector_t sel,        ;; selector of segment to set limit of
  474. ;;        uLong limit);        ;; desired segment limit
  475. ;;
  476. ;;
  477. ;; Description:
  478. ;;
  479. ;;    This function sets the limit of the segment specified by the
  480. ;;    sel argument to the value given by the limit argument.
  481. ;;
  482. ;; DPMI reference: INT 31h AX=0008h
  483. ;;
  484. ;; Version 1.0 Error returns:
  485. ;;
  486. ;;    8021h    invalid value
  487. ;;    8022h    invalid selecotr
  488. ;;    8023h    invalid linear address
  489.  
  490. DPMISetSegmentLimit PROC C    \
  491.     sel:selector_t,        \
  492.     limit:uLong
  493.  
  494.     mov    ax, 0008h
  495.     mov    bx, sel
  496.     ldlong    cx, dx, limit
  497.     int    31h
  498.     jc    @@exit
  499.     xor    ax, ax
  500. @@exit:
  501.     ret
  502. DPMISetSegmentLimit ENDP
  503.  
  504. ;;======================================================================
  505. ;; Function: Get Segment Attributes
  506. ;;
  507. ;; Synopsis:
  508. ;;
  509. ;;    int DPMIGetSegmentAttributes(
  510. ;;        selector_t sel,        ;; selector of segment to get attribs
  511. ;;        uChar *arb,        ;; receives access rights/type byte
  512. ;;        uChar *arb386);        ;; receives extended access byte(386+)
  513. ;;
  514. ;;
  515. ;; Description:
  516. ;;
  517. ;;    This function gets the attributes of the segment specified by the
  518. ;;    sel argument. The location pointed to by the arb argument receives
  519. ;;    the 6th byte of the descriptor, and the location pointed to by
  520. ;;    the arb386 argument returns the 8th byte of the descriptor.  This
  521. ;;    function is implemented with the LAR instruction.
  522. ;;
  523. ;; DPMI reference: Not a true DPMI function, but included for completeness.
  524. ;;
  525.  
  526. DPMIGetSegmentAttributes PROC C    \
  527.     sel:selector_t,        \
  528.     arb:PTR,        \
  529.     arb386:PTR
  530.  
  531.     mov    ax, 0400h        ;; check processor type
  532.     int    31h
  533.     cmp    cl, 2            ;; 2 means 286
  534.     je    @@is286
  535. .386p
  536.     movzx    eax, sel
  537.     lar    eax, eax
  538.     jnz    @@fail            ;; zf=0 means cannot access descriptor
  539.  
  540.     shr    eax, 8
  541.     ldptr    bx, arb386
  542.     mov    [bx], ah
  543.     jmp    short getArb
  544. .286p
  545. @@is286:
  546.     ldptr    bx, arb386
  547.     mov    byte ptr [bx], 0
  548.  
  549. getArb:
  550.     lar    ax, sel
  551.     jnz    @@fail
  552.     ldptr    bx, arb
  553.     mov    [bx], ah
  554.  
  555.     xor    ax, ax
  556.     jmp    short @@exit
  557. @@fail:
  558.     mov    ax, 1
  559. @@exit:
  560.     ret
  561. DPMIGetSegmentAttributes ENDP
  562.  
  563. ;;======================================================================
  564. ;; Function: Set Segment Attributes
  565. ;;
  566. ;; Synopsis:
  567. ;;
  568. ;;    int DPMISetSegmentAttributes(
  569. ;;        selector_t sel,        ;; selector of segment to set attribs
  570. ;;        uChar arb,        ;; access rights/type byte
  571. ;;        uChar arb386);        ;; extended access byte (386+)
  572. ;;
  573. ;;
  574. ;; Description:
  575. ;;
  576. ;;    This function sets the attributes of the segment specified by
  577. ;;    the sel argument.  The arb argument is the 6th byte of the 
  578. ;;    descriptor, and the arb386 argument is the 8th byte of the 
  579. ;;    descriptor.  Attempts to set privilege levels more privileged
  580. ;;    than the client level will fail.
  581. ;;
  582. ;; DPMI reference: INT 31h AX=0009h
  583. ;;
  584. ;; Version 1.0 Error returns:
  585. ;;
  586. ;;    8021h    invalid value
  587. ;;    8022h    invalid selector
  588. ;;    8025h    invalid linear address
  589.  
  590. DPMISetSegmentAttributes PROC C    \
  591.     sel:selector_t,        \
  592.     arb:uChar,        \
  593.     arb386:uChar
  594.  
  595.     mov    ax, 0009h
  596.     mov    bx, sel
  597.     mov    cl, arb
  598.     mov    ch, arb386
  599.     int    31h
  600.     jc    @@exit
  601.     xor    ax, ax
  602. @@exit:
  603.     ret
  604. DPMISetSegmentAttributes ENDP
  605.  
  606. ;;======================================================================
  607. ;; Function: Create Alias Descriptor
  608. ;;
  609. ;; Synopsis:
  610. ;;
  611. ;;    int DPMICreateAlias(
  612. ;;        selector_t sel,        ;; selector to create alias for
  613. ;;        selector_t *alias);    ;; receives selector of alias segment
  614. ;;
  615. ;;
  616. ;; Description:
  617. ;;
  618. ;;    This function creates a descriptor with the same base and limit
  619. ;;    as the descriptor specified by the sel argument.  It writes the
  620. ;;    selector of the alias descriptor at the address pointed to by
  621. ;;    the alias argument.  The descriptor that this function creates is
  622. ;;    of type data.  The DPMI host does not maintain an association
  623. ;;    between the aliased descriptors.
  624. ;;
  625. ;; DPMI reference: INT 31h AX=000Ah
  626. ;;
  627. ;; Version 1.0 Error returns:
  628. ;;
  629. ;;    8011h    descriptor unavailable
  630. ;;    8022h    invalid selector
  631.  
  632. DPMICreateAlias PROC C    \
  633.     sel:selector_t,    \
  634.     aliasSel:PTR
  635.  
  636.     mov    ax, 000Ah
  637.     mov    bx, sel
  638.     int    31h
  639.     jc    @@exit
  640.  
  641.     ldptr    bx, aliasSel
  642.     mov    [bx], ax
  643.     xor    ax, ax
  644. @@exit:
  645.     ret
  646. DPMICreateAlias ENDP
  647.  
  648. ;;======================================================================
  649. ;; Function: Get Raw LDT Descriptor
  650. ;;
  651. ;; Synopsis:
  652. ;;
  653. ;;    int DPMIGetDescriptor(
  654. ;;        selector_t sel,                ;; descriptor to get
  655. ;;        struct descriptor_t *descriptor);    ;; struct to receive
  656. ;;
  657. ;;
  658. ;; Description:
  659. ;;    This function copies the contents of the LDT descriptor specified
  660. ;;    by the sel argument to the structure pointed to by the descriptor
  661. ;;    argument.
  662. ;;
  663. ;; DPMI reference: INT 31h AX=000Bh
  664. ;;
  665. ;; Version 1.0 Error returns:
  666. ;;
  667. ;;    8022h    invalid selector
  668.  
  669. DPMIGetDescriptor PROC C USES DI,    \
  670.     sel:selector_t,            \
  671.     descriptor:PTR
  672.  
  673.     mov    ax, 000Bh
  674.     mov    bx, sel
  675.     ldptr    di, descriptor, es
  676.     int    31h
  677.     jc    @@exit
  678.     xor    ax, ax
  679. @@exit:
  680.     ret
  681. DPMIGetDescriptor ENDP
  682.  
  683. ;;======================================================================
  684. ;; Function: Set Raw LDT Descriptor
  685. ;;
  686. ;; Synopsis:
  687. ;;
  688. ;;    int DPMISetDescriptor(
  689. ;;        selector_t sel,                ;; descriptor to set
  690. ;;        struct descriptor_t *descriptor);    ;; descriptor contents
  691. ;;
  692. ;;
  693. ;; Description:
  694. ;;
  695. ;;    This function copies the contents of the structure pointed to
  696. ;;    by the descriptor argument to the LDT entry specified by the
  697. ;;    sel argument.  If the present bit is set, the 
  698. ;;
  699. ;; DPMI reference: INT 31h AX=000Ch
  700. ;;
  701. ;; Version 1.0 Error returns:
  702. ;;
  703. ;;    8021h    invalid value
  704. ;;    8022h    invalid selector
  705. ;;    8025h    invalid linear address
  706.  
  707. DPMISetDescriptor PROC C USES DI, \
  708.     sel:selector_t,          \
  709.     descriptor:PTR
  710.  
  711.     mov    ax, 000Ch
  712.     mov    bx, sel
  713.     ldptr    di, descriptor, es
  714.     int    31h
  715.     jc    @@exit
  716.     xor    ax, ax
  717. @@exit:
  718.     ret
  719. DPMISetDescriptor ENDP
  720.  
  721. ;;======================================================================
  722. ;; Function: Allocate Specific LDT Descriptor
  723. ;;
  724. ;; Synopsis:
  725. ;;
  726. ;;    int DPMIAllocateSpecificDescriptor(
  727. ;;        selector_t sel);    ;; selector of descriptor to allocate
  728. ;;
  729. ;;
  730. ;; Description:
  731. ;;    This function allocates a specific LDT descriptor in the range
  732. ;;    04h to 7Ch. It is intended for use only with DOS extended applications
  733. ;;    that require compatibility with pre-DPMI environments.
  734. ;;
  735. ;; DPMI reference: INT 31h AX=000Dh
  736. ;;
  737. ;; Version 1.0 Error returns:
  738. ;;
  739. ;;    8011h    descriptor unavailable
  740. ;;    8022h    invalid selector
  741.  
  742. DPMIAllocateSpecificDescriptor PROC C    \
  743.     sel:selector_t
  744.  
  745.     mov    ax, 000Dh
  746.     mov    bx, sel
  747.     int    31h
  748.     jc    @@exit
  749.     xor    ax, ax
  750. @@exit:
  751.     ret    
  752. DPMIAllocateSpecificDescriptor ENDP
  753.  
  754. ;;======================================================================
  755. ;; Function: Allocate DOS Memory Block
  756. ;;
  757. ;; Synopsis:
  758. ;;
  759. ;;    int DPMIAllocateDOSMemory(
  760. ;;        uShort nParas,        ;; number of paragraphs to allocate
  761. ;;        uShort *para,        ;; receives para of alloc'ed block
  762. ;;        selector_t *sel,    ;; receives selector of alloc'ed block
  763. ;;        uShort *maxParas);    ;; receives max avail in fail case
  764. ;;
  765. ;;
  766. ;; Description:
  767. ;;
  768. ;;    This function allocates a block of memory from DOS.  The block so
  769. ;;    allocated is guaranteed to reside below 1 MB, and thus be addressable
  770. ;;    by real mode code.  The desired size of the block is specified by 
  771. ;;    the nParas argument, which should be set to the number of paragraphs
  772. ;;    (16 bytes each) for the block.  The DPMI host provides both a 
  773. ;;    paragraph address (which is written at the address pointed to by the
  774. ;;    para argument),and a selector (which is written at the address 
  775. ;;    pointed to by the sel argument.
  776. ;;
  777. ;;    If the requested size of the block is greater than 64 KB (4096 paras),
  778. ;;    the DPMI host creates a set of descriptors sufficient to span the
  779. ;;    allocated region, with consecutive selectors and bases that differ
  780. ;;    by 64 KB.
  781. ;;
  782. ;;    In the case where there is insufficient memory to satisfy the request,
  783. ;;    the DPMI host writes the maximum number of paragraphs available to
  784. ;;    the address pointed to by the maxParas argument.
  785. ;;
  786. ;;
  787. ;; DPMI reference: INT 31h AX=0100h
  788. ;;
  789. ;; Error returns (valid for version 0.9)
  790. ;;
  791. ;;    0007h    memory control blocks damaged
  792. ;;    0008h    insufficient memory
  793.  
  794. DPMIAllocateDOSMemory PROC C    \
  795.     nParas:uShort,        \
  796.     para:PTR,        \
  797.     sel:PTR,        \
  798.     maxParas:PTR
  799.  
  800.     mov    ax, 0100h
  801.     mov    bx, nParas
  802.     int    31h
  803.     jc    @@fail
  804.  
  805.     ldptr    bx, para
  806.     mov    [bx], ax
  807.     ldptr    bx, sel
  808.     mov    [bx], dx
  809.  
  810.     xor    ax,ax
  811.     jmp    short @@exit
  812. @@fail:
  813.     mov    cx, bx
  814.     ldptr    bx, maxParas
  815.     mov    [bx], cx
  816. @@exit:
  817.     ret
  818. DPMIAllocateDOSMemory ENDP
  819.  
  820. ;;======================================================================
  821. ;; Function: Free DOS Memory Block
  822. ;;
  823. ;; Synopsis:
  824. ;;
  825. ;;    int DPMIFreeDOSMemory(
  826. ;;        selector_t sel);    ;; selector of block to free
  827. ;;
  828. ;;
  829. ;; Description:
  830. ;;
  831. ;;    This function frees a DOS memory block allocated by the function
  832. ;;    DPMIAllocateDOSMemory.  The argument is the selector of the 
  833. ;;    block to be freed. If the DOS block is larger than 64 KB, all of
  834. ;;    the descriptors that were allocated for the block are freed.d
  835. ;;
  836. ;; DPMI reference: INT 31h AX=0101h
  837. ;;
  838. ;; Error returns (valid for version 0.9):
  839. ;;
  840. ;;    0007h    memory control blocks damaged
  841. ;;    0009h    incorrect memory segment specified
  842.  
  843. DPMIFreeDOSMemory PROC C    \
  844.     sel:selector_t
  845.  
  846.     mov    ax, 0101h
  847.     mov    dx, sel
  848.     int    31h
  849.     jc    @@exit
  850.     xor    ax, ax
  851. @@exit:
  852.     ret
  853. DPMIFreeDOSMemory ENDP
  854.  
  855. ;;======================================================================
  856. ;; Function: Resize DOS Memory Block
  857. ;;
  858. ;; Synopsis:
  859. ;;
  860. ;;    int DPMIResizeDOSMemory(
  861. ;;        selector_t sel,        ;; selector of block to resize
  862. ;;        uShort nParas,        ;; desired size of block in paras
  863. ;;        uShort *maxParas);    ;; receives max paras available
  864. ;;
  865. ;;
  866. ;; Description:
  867. ;;
  868. ;;    This function changes the size of a block that was allocated with
  869. ;;    the function DPMIAllocateDOSMemory.  The nParas argument specifies
  870. ;;    the desired new size of the block, in paragraphs.  The sel argument
  871. ;;    is the selector of the block to be resized.
  872. ;;
  873. ;;    In the case where there is insufficient memory to satisfy the request,
  874. ;;    the DPMI host writes the maximum number of paragraphs available to
  875. ;;    the address pointed to by the maxParas argument.
  876. ;;
  877. ;; DPMI reference: INT 31h AX=102h
  878. ;;
  879. ;; Error returns (valid for version 0.9):
  880. ;;
  881. ;;    0007h    memory control blocks damaged
  882. ;;    0008h    insufficient memory
  883. ;;    0009h    incorrect memory segment
  884.  
  885. DPMIResizeDOSMemory PROC C    \
  886.     sel:selector_t,        \
  887.     nParas:uShort,        \
  888.     maxParas:PTR
  889.  
  890.     mov    ax, 0102h
  891.     mov    bx, nParas
  892.     mov    dx, sel
  893.     int    31h
  894.     jc    @@fail
  895.  
  896.     xor    ax, ax
  897.     jmp    short @@exit
  898. @@fail:
  899.     mov    cx, bx
  900.     ldptr    bx, maxParas
  901.     mov    [bx], cx
  902. @@exit:
  903.     ret
  904. DPMIResizeDOSMemory ENDP
  905.  
  906. ;;======================================================================
  907. ;; Function: Get Real Mode Interrupt Vector
  908. ;;
  909. ;; Synopsis:
  910. ;;
  911. ;;    void DPMIGetRealInterruptVector(
  912. ;;        uChar vector,            ;; vector number to get
  913. ;;        void (far* *realIsr)());    ;; receives real vector
  914. ;;
  915. ;;
  916. ;; Description:
  917. ;;
  918. ;;    This function retrieves the real mode paragraph:offset address of
  919. ;;    the real mode interrupt handler specified by the vector argument.
  920. ;;    The handler address is written to the address pointed to by the
  921. ;;    realIsr argument.
  922. ;;
  923. ;;
  924. ;; DPMI reference: INT 31h AX=0200h
  925. ;;
  926.  
  927. DPMIGetRealInterruptVector PROC C    \
  928.     vector:uChar,            \
  929.     realIsr:PTR
  930.  
  931.     mov    ax, 0200h
  932.     mov    bl, vector
  933.     int    31h
  934.     ldptr    bx, realIsr
  935.     stlong    [bx], cx, dx
  936.  
  937.     ret
  938. DPMIGetRealInterruptVector ENDP
  939.  
  940. ;;======================================================================
  941. ;; Function: Set Real Mode Interrupt Vector
  942. ;;
  943. ;; Synopsis:
  944. ;;
  945. ;;    void DPMISetRealInterruptVector(
  946. ;;        uChar vector,            ;; vector number to set
  947. ;;        void (far *realIsr)());        ;; new real vector
  948. ;;
  949. ;;
  950. ;; Description:
  951. ;;
  952. ;;    This function sets the real mode interrupt vector specified by the
  953. ;;    vector argument to the value in the realIsr argument.  The handler
  954. ;;    address in realIsr must be a real mode paragraph:offset address.
  955. ;;
  956. ;; DPMI reference: INT 31h AX=0201h
  957. ;;
  958.  
  959. DPMISetRealInterruptVector PROC C    \
  960.     vector:uChar,            \
  961.     realIsr:FAR PTR
  962.  
  963.     mov    ax, 0201h
  964.     mov    bl, vector
  965.     ldlong    cx, dx, realIsr
  966.     int    31h
  967.     ret
  968. DPMISetRealInterruptVector ENDP
  969.  
  970. ;;======================================================================
  971. ;; Function: Get Processor Exception Vector
  972. ;;
  973. ;; Synopsis:
  974. ;;
  975. ;;    int DPMIGetExceptionVector(
  976. ;;        uChar exception,        ;; exception number to get
  977. ;;        void (far* *excHandler)());    ;; receives handler address
  978. ;;
  979. ;;
  980. ;; Description:
  981. ;;
  982. ;;    This function retrieves the address of the exception handler
  983. ;;    specified by the exception argument (range 0-1Fh).  The handler
  984. ;;    address is written to the address pointed to by the 
  985. ;;    excHandler argument.
  986. ;;    
  987. ;; DPMI reference: INT 31h AX=0202h
  988. ;;
  989. ;; Version 1.0 Error returns:
  990. ;;
  991. ;;    8021h    invalid value
  992.  
  993. DPMIGetExceptionVector PROC C    \
  994.     exception:uChar,    \
  995.     excHandler:PTR
  996.  
  997.     mov    ax, 0202h
  998.     mov    bl, exception
  999.     int    31h
  1000.     jc    @@exit
  1001.  
  1002.     ldptr    bx, excHandler
  1003.     stlong    [bx], cx, dx
  1004.  
  1005.     xor    ax, ax
  1006. @@exit:
  1007.     ret
  1008. DPMIGetExceptionVector ENDP
  1009.  
  1010. ;;======================================================================
  1011. ;; Function: Set Processor Exception Vector
  1012. ;;
  1013. ;; Synopsis:
  1014. ;;
  1015. ;;    int DPMISetExceptionVector(
  1016. ;;        uChar exception,        ;; exception number to set
  1017. ;;        void (far *excHandler)());    ;; new handler address
  1018. ;;
  1019. ;;
  1020. ;; Description:
  1021. ;;
  1022. ;;    This function sets the exception vector specified by the
  1023. ;;    exception argument to the value in the excHandler argument.  
  1024. ;;
  1025. ;;    The exception handler is defined as follows:
  1026. ;;
  1027. ;;        void _saveregs _far excHandler(struct excFrame);
  1028. ;;
  1029. ;;    The exception handler may modify the fields of the excFrame structure.
  1030. ;;    When the handler returns, the DPMI host uses the new values from
  1031. ;;    the structure to restart the faulting client.
  1032. ;;
  1033. ;; DPMI reference: INT 31h AX=0203h
  1034. ;;
  1035. ;; Version 1.0 Error returns:
  1036. ;;
  1037. ;;    8021h    invalid value
  1038. ;;    8022h    invalid selector
  1039.  
  1040. DPMISetExceptionVector PROC C    \
  1041.     exception:uChar,    \
  1042.     excHandler:FAR PTR
  1043.     
  1044.     mov    ax, 0203h
  1045.     mov    bl, exception
  1046.     ldlong    cx, dx, excHandler
  1047.     int    31h
  1048.     jc    @@exit
  1049.  
  1050.     xor    ax, ax
  1051. @@exit:
  1052.     ret
  1053. DPMISetExceptionVector ENDP
  1054.  
  1055. ;;======================================================================
  1056. ;; Function: Get Protected Mode Interrupt Vector
  1057. ;;
  1058. ;; Synopsis:
  1059. ;;
  1060. ;;    void DPMIGetProtInterruptVector(
  1061. ;;        uChar vector,            ;; interrupt vector to get
  1062. ;;        void (far* *protIsr)());    ;; receives interrupt vector
  1063. ;;
  1064. ;; Description:
  1065. ;;
  1066. ;;    This function retrieves the protected mode interrupt vector
  1067. ;;    specified by the vector argument.  The selector:offset address of
  1068. ;;    the current interrupt handler is written to the address pointed to
  1069. ;;    by the protIsr argument.
  1070. ;;
  1071. ;; DPMI reference: INT 31h AX=0204h
  1072. ;;
  1073.  
  1074. DPMIGetProtInterruptVector PROC C    \
  1075.     vector:uChar,            \
  1076.     protIsr:PTR
  1077.  
  1078.     mov    ax, 0204h
  1079.     mov    bl, vector
  1080.     int    31h
  1081.     ldptr    bx, protIsr
  1082.     stlong    [bx], cx, dx
  1083.  
  1084.     ret
  1085. DPMIGetProtInterruptVector ENDP
  1086.  
  1087. ;;======================================================================
  1088. ;; Function: Set Protected Mode Interrupt Vector
  1089. ;;
  1090. ;; Synopsis:
  1091. ;;
  1092. ;;    int DPMISetProtInterruptVector(
  1093. ;;        uChar vector,            ;; interrupt vector to set
  1094. ;;        void (far *protIsr)());        ;; new handler address
  1095. ;;
  1096. ;;
  1097. ;; Description:
  1098. ;;
  1099. ;;    This function sets the address of the protected mode interrupt
  1100. ;;    handler for the vector specified by the vector arugment.  The
  1101. ;;    protIsr argument is the selector:offset of the desired new
  1102. ;;    handler.
  1103. ;;
  1104. ;; DPMI reference: INT 31h AX=0205h
  1105. ;;
  1106. ;; Version 1.0 Error returns:
  1107. ;;
  1108. ;;    8022h    invalid selector
  1109.  
  1110. DPMISetProtInterruptVector PROC C    \
  1111.     vector:uChar,            \
  1112.     protIsr:FAR PTR
  1113.  
  1114.     mov    ax, 0205h
  1115.     mov    bl, vector
  1116.     ldlong    cx, dx, protIsr
  1117.     int    31h
  1118.     jc    @@exit
  1119.     xor    ax, ax
  1120. @@exit:
  1121.     ret
  1122. DPMISetProtInterruptVector ENDP
  1123.  
  1124. ;;======================================================================
  1125. ;; Function: Issue Real Mode Interrupt
  1126. ;;
  1127. ;; Synopsis:
  1128. ;;
  1129. ;;    int DPMIIssueRealInterrupt(
  1130. ;;        uChar vector,            ;; interrupt to issue
  1131. ;;        uShort nArgBytes,        ;; number of bytes of args
  1132. ;;        struct dpmiRegs_t *regs,    ;; real mode register state
  1133. ;;        ...);
  1134. ;;
  1135. ;;
  1136. ;; Description:
  1137. ;;
  1138. ;;    This function switches to real mode and issues the interrupt 
  1139. ;;    specified by the vector argument.  Prior to issuing the interrupt,
  1140. ;;    the DPMI host loads the processor registers with the contents of
  1141. ;;    the structure pointed to by the regs argument.  When the interrupt
  1142. ;;    handler returns, the DPMI host updates the register structure to
  1143. ;;    reflect changes caused by the interrupt handler.
  1144. ;;
  1145. ;;    The CS:IP field of the real call structure is ignored, because the
  1146. ;;    execution address is determined by the real mode interrupt vector.
  1147. ;;
  1148. ;; DPMI reference: INT 31h AX=0300h
  1149. ;;
  1150. ;; Version 1.0 Error returns:
  1151. ;;
  1152. ;;    8012h    linear memory unavailable
  1153. ;;    8013h    physical memory unavailable
  1154. ;;    8014h    backing store unavailable
  1155. ;;    8021h    invalid value
  1156.  
  1157. DPMIIssueRealInterrupt PROC C USES DS SI DI,    \
  1158.     vector:BYTE,                \
  1159.     nArgBytes:uShort,            \
  1160.     regs:PTR,                \
  1161.     arguments:BYTE
  1162.  
  1163.     mov    cx, nArgBytes        ;; copy stack arguments
  1164.     jcxz    @@doCall
  1165.     sub    sp, cx
  1166.     mov    di, sp
  1167.     lea    si, arguments
  1168.     mov    ax, ss
  1169.     mov    ds, ax
  1170.     mov    es, ax
  1171.     cld
  1172.     rep movsb
  1173. @@doCall:
  1174.     mov    ax, 0300h
  1175.     xor    bh, bh
  1176.     mov    bl, vector
  1177.     mov    cx, nArgBytes
  1178.     ldptr    di, regs, es
  1179.     int    31h
  1180.     jc    @@exit
  1181.     xor    ax, ax
  1182. @@exit:
  1183.     add    sp, nArgBytes
  1184.     ret
  1185. DPMIIssueRealInterrupt ENDP
  1186.  
  1187. ;;======================================================================
  1188. ;; Function: Call Real Mode Procedure with Far Return
  1189. ;;
  1190. ;; Synopsis:
  1191. ;;
  1192. ;;    int DPMICallRealProcedure(
  1193. ;;        uShort nArgBytes,        ;; number of bytes of args
  1194. ;;        struct dpmiRegs_t *regs,    ;; real mode register state
  1195. ;;        ...);                ;; function arguments
  1196. ;;
  1197. ;; Description:
  1198. ;;
  1199. ;;    This function causes the DPMI host to switch to real mode, push
  1200. ;;    zero or more argument bytes on the stack, and call the far function
  1201. ;;    indicated by the CS:IP fields of the real call structure pointed
  1202. ;;    to by the regs argument.  The number of argument bytes to push is
  1203. ;;    given by the nArgBytes argument, and the function arguments should
  1204. ;;    follow the pointer to the real call structure in the arugment list.
  1205. ;;    The real function must return on the same stack on which it was
  1206. ;;    called.
  1207. ;;
  1208. ;;    The DPMI host reloads the register structure with the register 
  1209. ;;    current register state when the far function returns.  
  1210. ;;
  1211. ;; DPMI reference: INT 31h AX=0301h
  1212. ;;
  1213. ;; Version 1.0 Error returns:
  1214. ;;
  1215. ;;    8012h    linear memory unavailable
  1216. ;;    8013h    physical memory unavailable
  1217. ;;    8014h    backing store unavailable
  1218. ;;    8021h    invalid value
  1219.  
  1220. DPMICallRealProcedure PROC C USES DS SI DI,    \
  1221.     nArgBytes:uShort,            \
  1222.     regs:PTR,                \
  1223.     arguments:BYTE
  1224.  
  1225.     mov    cx, nArgBytes        ;; copy stack arguments
  1226.     jcxz    @@doCall
  1227.     sub    sp, cx
  1228.     mov    di, sp
  1229.     lea    si, arguments
  1230.     mov    ax, ss
  1231.     mov    ds, ax
  1232.     mov    es, ax
  1233.     cld
  1234.     rep movsb
  1235. @@doCall:
  1236.     mov    ax, 0301h
  1237.     xor    bh, bh
  1238.     mov    cx, nArgBytes
  1239.     ldptr    di, regs, es
  1240.     int    31h
  1241.     jc    @@exit
  1242.     xor    ax, ax
  1243. @@exit:
  1244.     add    sp, nArgBytes
  1245.     ret
  1246. DPMICallRealProcedure ENDP
  1247.  
  1248. ;;======================================================================
  1249. ;; Function: Call Real Mode Procedure with IRET
  1250. ;;
  1251. ;; Synopsis:
  1252. ;;
  1253. ;;    int DPMICallRealInterruptProcedure(
  1254. ;;        uShort nArgBytes,        ;; number of bytes of args
  1255. ;;        struct dpmiRegs_t *regs,    ;; real mode register state
  1256. ;;        ...);                ;; function arguments.
  1257. ;;    
  1258. ;;
  1259. ;; Description:
  1260. ;;
  1261. ;;    This function is identical to DPMICallRealProcedure, except that
  1262. ;;    it is used to call a real function that returns with an IRET
  1263. ;;    instead of a RETF.
  1264. ;;
  1265. ;; DPMI reference: INT 31h AX=0302h
  1266. ;;
  1267. ;; Version 1.0 Error returns:
  1268. ;;
  1269. ;;    8012h    linear memory unavailable
  1270. ;;    8013h    physical memory unavailable
  1271. ;;    8014h    backing store unavailable
  1272. ;;    8021h    invalid value
  1273.  
  1274. DPMICallRealInterruptProcedure PROC C USES DS SI DI, \
  1275.     nArgBytes:uShort,            \
  1276.     regs:PTR,                \
  1277.     arguments:BYTE
  1278.  
  1279.     mov    cx, nArgBytes        ;; copy stack arguments
  1280.     jcxz    @@doCall
  1281.     sub    sp, cx
  1282.     mov    di, sp
  1283.     lea    si, arguments
  1284.     mov    ax, ss
  1285.     mov    ds, ax
  1286.     mov    es, ax
  1287.     cld
  1288.     rep movsb
  1289. @@doCall:
  1290.     mov    ax, 0302h
  1291.     xor    bh, bh
  1292.     mov    cx, nArgBytes
  1293.     ldptr    di, regs, es
  1294.     int    31h
  1295.     jc    @@exit
  1296.     xor    ax, ax
  1297. @@exit:
  1298.     add    sp, nArgBytes
  1299.     ret
  1300. DPMICallRealInterruptProcedure ENDP
  1301.  
  1302. ;;======================================================================
  1303. ;; Function: Allocate Real Mode Callback
  1304. ;;
  1305. ;; Synopsis:
  1306. ;;
  1307. ;;    int DPMIAllocateRealCallBack(
  1308. ;;        struct dpmiRegs_t *regs,    ;; address of static reg state
  1309. ;;        void (far *handler)(),        ;; prot mode callback handler
  1310. ;;        void (far* *cbAddr)());        ;; receives real callback addr
  1311. ;;
  1312. ;; Description:
  1313. ;;
  1314. ;;    This function allocates a real mode callback from the DPMI host.
  1315. ;;    A real mode callback is a real mode address (paragraph:offset) that
  1316. ;;    a real mode caller uses to invoke a protected mode callback
  1317. ;;    handler.  This provides a mechanism for calling protected mode
  1318. ;;    from real mode.  
  1319. ;;
  1320. ;;    The cbAddr argument points to the location to receive the real mode
  1321. ;;    callback address.  When called, the DPMI host passes control to
  1322. ;;    the protected mode address specified by the handler argument. 
  1323. ;;
  1324. ;;    The protected mode handler  is passed (in ES:DI) a pointer to the 
  1325. ;;    real mode call structure whose address is passed  to this function
  1326. ;;    in the regs argument.  Therefore, this structure should be statically
  1327. ;;    allocated.  The DPMI host is responsible for loading the structure
  1328. ;;    with the register state at the time of the callback prior to passing
  1329. ;;    it to the protected mode callback handler. The handler is also 
  1330. ;;    passed (in DS:SI) the address of the real mode stack.
  1331. ;;
  1332. ;;    The DPMI host uses the register state in the call structure
  1333. ;;    to restart the real mode caller.  It is the responsibility of the
  1334. ;;    protected mode handler to locate the real mode return address on
  1335. ;;    the real mode stack, and store it in the CS:IP fields of the call
  1336. ;;    structure in order to effect a return from the callback.
  1337. ;;
  1338. ;; DPMI reference: INT 31h AX=0303h
  1339. ;;
  1340. ;; Version 1.0 Error returns:
  1341. ;;
  1342. ;;    8015h    callback unavailable
  1343.  
  1344. DPMIAllocateRealCallBack PROC C    USES DS SI DI,     \
  1345.     regs:PTR,                \
  1346.     handler:FAR PTR,            \
  1347.     cbAddr:PTR
  1348.  
  1349.     push    ds
  1350.     mov    ax, 0303h
  1351.     ldptr    di, regs, es
  1352.     ldlong    ds, si, handler
  1353.     int    31h
  1354.     jc    @@fail
  1355.     
  1356.     pop    ds
  1357.     ldptr    bx, cbAddr
  1358.     stlong    [bx], cx, dx
  1359.     xor    ax, ax
  1360.     jmp    short @@exit
  1361. @@fail:
  1362.     pop    ds
  1363. @@exit:
  1364.     ret
  1365. DPMIAllocateRealCallBack ENDP
  1366.  
  1367. ;;======================================================================
  1368. ;; Function: Free Real Mode Callback
  1369. ;;
  1370. ;; Synopsis:
  1371. ;;
  1372. ;;    int DPMIFreeRealCallBack(
  1373. ;;        void (far *cbAddr)());        ;; callback to free
  1374. ;;
  1375. ;;
  1376. ;; Description:
  1377. ;;
  1378. ;;    This function frees a real mode callback allocated by 
  1379. ;;    DPMIAllocateRealCallBack.  The cbAddr is the callback
  1380. ;;    address to be freed.
  1381. ;;
  1382. ;; DPMI reference: INT 31h AX=0303h
  1383. ;;
  1384. ;; Version 1.0 Error returns:
  1385. ;;
  1386. ;;    8024h    invalid callback address
  1387.  
  1388. DPMIFreeRealCallBack PROC C    \
  1389.     cbAddr:FAR PTR
  1390.  
  1391.     mov    ax, 0304h
  1392.     ldlong    cx, dx, cbAddr
  1393.     int    31h
  1394.     jc    @@exit
  1395.     xor    ax, ax
  1396. @@exit:
  1397.     ret
  1398. DPMIFreeRealCallBack ENDP
  1399.  
  1400. ;;======================================================================
  1401. ;; Function: Get State Save/Restore Procedure Addresses
  1402. ;;
  1403. ;; Synopsis:
  1404. ;;
  1405. ;;    void DPMIGetStateSaveRestoreProcs(
  1406. ;;        uShort *stateSize,        ;; size of state info
  1407. ;;        void (far* *realProc)(),    ;; receives real save/rst proc
  1408. ;;        void (far* *protProc)());    ;; receives prot save/rst proc
  1409. ;;
  1410. ;; Description:
  1411. ;;
  1412. ;;    This function retrieves information from the DPMI host that
  1413. ;;    is required for saving and restoring the client state when
  1414. ;;    using the raw mode switch function.
  1415. ;;
  1416. ;;    The DPMI specification requires that clients save their state
  1417. ;;    prior to making a raw mode switch, and subsequently restore it.
  1418. ;;    This function provides the size of the state information, and
  1419. ;;    the both the protected mode and real mode addresses of functions
  1420. ;;    to call to save and restore the client state.
  1421. ;;
  1422. ;;    The size of the state information, in bytes, is stored at the
  1423. ;;    address pointed to by the stateSize argument.  The address of the
  1424. ;;    far procedure to call from real mode to save or restore the client
  1425. ;;    state is stored at the address pointed to by the realProc argument.
  1426. ;;    The address of the far procedure to call from protected mode to
  1427. ;;    save and restore the client state is stored at the address pointed
  1428. ;;    to by the protProc argument.
  1429. ;;
  1430. ;;    The state save/restore procedures are called with AL=0 to save the
  1431. ;;    state, and AL=1 to restore the state.  In both cases, ES:DI points
  1432. ;;    to the state information buffer.
  1433. ;;
  1434. ;;
  1435. ;; DPMI reference: INT 31h AX=0305h
  1436.  
  1437. DPMIGetStateSaveRestoreProcs PROC C USES SI DI,    \
  1438.     stateSize:PTR,        \
  1439.     realProc:PTR,        \
  1440.     protProc:PTR
  1441.  
  1442.     mov    ax, 0305h
  1443.     int    31h
  1444.  
  1445.     mov    dx, bx
  1446.  
  1447.     ldptr    bx, stateSize
  1448.     mov    [bx], ax
  1449.     ldptr    bx, realProc
  1450.     stlong    [bx], dx, cx
  1451.     ldptr    bx, protProc
  1452.     stlong    [bx], si, di
  1453.  
  1454.     ret
  1455. DPMIGetStateSaveRestoreProcs ENDP
  1456.  
  1457. ;;======================================================================
  1458. ;; Function: Save Or Restore Client State for Raw Switch
  1459. ;;
  1460. ;; Synopsis:
  1461. ;;
  1462. ;;    void DPMISaveOrRestoreState(
  1463. ;;        int saveRestore,        ;; 0=save 1=restore
  1464. ;;        uChar *stateBuffer,        ;; pointer to state buffer
  1465. ;;        void (far *procAddr)());    ;; procedure to call
  1466. ;;            
  1467. ;; Description:            
  1468. ;;
  1469. ;;    This function invokes the save/restore procedure whose address
  1470. ;;    is specified by the procAddr argument.  The stateBuffer argument
  1471. ;;    points to the buffer to supply or receive the client state. Its
  1472. ;;    size is determined by calling DPMIGetStateSaveRestoreProcs. The
  1473. ;;    saveRestore argument is zero to perform state save, or one to
  1474. ;;    perform a state restore.
  1475.  
  1476. DPMISaveOrRestoreState PROC C USES DI,    \
  1477.     saveRestore:WORD,        \
  1478.     stateBuffer:PTR,        \
  1479.     procAddr:FAR PTR
  1480.  
  1481.     mov    ax, saveRestore
  1482.     ldptr    di, stateBuffer, es
  1483.     call    procAddr
  1484.     
  1485.     ret
  1486. DPMISaveOrRestoreState ENDP
  1487.  
  1488. ;;======================================================================
  1489. ;; Function: Get Raw Switch Procedure Addresses
  1490. ;;
  1491. ;; Synopsis:
  1492. ;;
  1493. ;;    void DPMIGetRawSwitchProc(
  1494. ;;        void (far* *realToProt)(),    ;; real to prot switch addr
  1495. ;;        void (far* *protToReal)());    ;; prot to real switch addr
  1496. ;;            
  1497. ;; Description:
  1498. ;;
  1499. ;;    This function retrieves information from the DPMI host that
  1500. ;;    is required for raw mode switching.  The address (paragraph:offset)
  1501. ;;    of the real to protected mode service is stored at the address
  1502. ;;    pointed to by the realToProt argument.  The address (selector:offset)
  1503. ;;    of the protected to real mode service is stored at the address
  1504. ;;    pointed to by the protToReal argument.
  1505. ;;
  1506. ;; DPMI reference: INT 31h AX=0306h
  1507.  
  1508. DPMIGetRawSwitchProc PROC C USES SI DI,    \
  1509.     realToProt:PTR,            \
  1510.     protToReal:PTR
  1511.     
  1512.     mov    ax,0306h
  1513.     int    31h
  1514.  
  1515.     mov    dx, bx
  1516.     ldptr    bx, realToProt
  1517.     stlong    [bx], dx, cx
  1518.     ldptr    bx, protToReal
  1519.     stlong    [bx], si, di
  1520.  
  1521.     ret
  1522. DPMIGetRawSwitchProc ENDP
  1523.  
  1524. ;;======================================================================
  1525. ;; Function: Do Raw Mode Switch
  1526. ;;
  1527. ;; Synopsis:
  1528. ;;
  1529. ;;    void DPMIDoRawSwitch(
  1530. ;;        void (far *switchAddr)(),    ;; switch service address
  1531. ;;        struct rawModeRegs_t *rawRegs);    ;; new register values
  1532. ;;
  1533. ;; Description:
  1534. ;;
  1535. ;;    This function invokes the raw switch service.  The switchAddr
  1536. ;;    argument is obtained from DPMIGetRawSwitchProc, and specifies
  1537. ;;    the address of the switch service to invoke.  When the function
  1538. ;;    returns, the processor will be in the alternate mode.  
  1539. ;;
  1540. ;;    The rawRegs argument points to the structure containing the register 
  1541. ;;    contents to be put in effect after the mode switch is effected.
  1542. ;;    The values in the structure MUST be aliases for the currently active
  1543. ;;    segment registers.  In other words, when switching from protected
  1544. ;;    to real mode, each segment register value in the structure must
  1545. ;;    be the paragraph equivalent of the current protected mode descriptor
  1546. ;;    value.  Likewise, when switching from real to protected mode, each
  1547. ;;    segment register value in the structure must be the selector that
  1548. ;;    maps the current paragraph in each segment register. These
  1549. ;;    requirements imply that this routine must execute only in the low
  1550. ;;    1 MB of the address space, and that the stack must also be in the
  1551. ;;    low 1 MB.
  1552. ;;
  1553. ;; DPMI reference: invoking the raw mode switch services
  1554.  
  1555. DPMIDoRawSwitch PROC C USES SI DI,     \
  1556.     switchAddr:FAR PTR,    \
  1557.     rawRegs:PTR
  1558.  
  1559.     ldptr    di, rawRegs
  1560.     mov    ax, [di].rawDS
  1561.     mov    cx, [di].rawES
  1562.     mov    dx, [di].rawSS
  1563.     mov    bx, sp
  1564.     mov    si, [di].rawCS
  1565.     mov    di, offset @@cont
  1566.     push    word ptr switchAddr+2    ;; push switch address and retf to it
  1567.     push    word ptr switchAddr
  1568.     retf
  1569. @@cont:
  1570.     ret
  1571. DPMIDoRawSwitch ENDP
  1572.  
  1573. ;;======================================================================
  1574. ;; Function: Get DPMI Host Version Information
  1575. ;;
  1576. ;; Synopsis:
  1577. ;;
  1578. ;;    void DPMIGetVersion(
  1579. ;;        uChar *major,        ;; receives major version number
  1580. ;;        uChar *minor,        ;; receives minor version number
  1581. ;;        uChar *processor,    ;; receives processor code
  1582. ;;        uShort *flags,        ;; receives flags
  1583. ;;        uChar *masterPIC,    ;; receives virtual master PIC base
  1584. ;;        uChar *slavePIC);    ;; receives virtual slave PIC base
  1585. ;;            
  1586. ;; Description:
  1587. ;;
  1588. ;;    This function retrieves version information from the DPMI host.
  1589. ;;    For version 0.9, the major version is zero and the minor version
  1590. ;;    is 90 (5Ah).  The processor codes are as follows:
  1591. ;;
  1592. ;;        2 => 80286, 3 => 80386, 4 => 80486 5-FFh => future
  1593. ;;
  1594. ;;    The bits of the flags word have the following meanings:
  1595. ;;
  1596. ;;        Bit    Meaning
  1597. ;;         0    0 = 16-bit host, 
  1598. ;;            1 = 32-bit host
  1599. ;;         1    0 = DOS runs in virtual 86 mode, 
  1600. ;;            1 = DOS runs in real
  1601. ;;         2    0 = no virtual memory support
  1602. ;;            1 = virtual memory supported
  1603. ;;    
  1604. ;; DPMI reference: INT 31h AX=0400h
  1605.  
  1606. DPMIGetVersion PROC C USES SI,    \
  1607.     major:PTR,    \
  1608.     minor:PTR,    \
  1609.     processor:PTR,    \
  1610.     flags:PTR,    \
  1611.     masterPIC:PTR,    \
  1612.     slavePIC:PTR
  1613.  
  1614.     mov    ax, 0400h
  1615.     int    31h
  1616.  
  1617.     ldptr    si, major
  1618.     mov    [si], ah
  1619.     ldptr    si, minor
  1620.     mov    [si], al
  1621.     ldptr    si, flags
  1622.     mov    [si], bx
  1623.     ldptr    si, processor
  1624.     mov    [si], cl
  1625.     ldptr    si, masterPIC
  1626.     mov    [si], dh
  1627.     ldptr    si, slavePIC
  1628.     mov    [si], dl
  1629.  
  1630.     ret
  1631. DPMIGetVersion ENDP
  1632.  
  1633. ;;======================================================================
  1634. ;; Function: Get Free Memory Information
  1635. ;;
  1636. ;; Synopsis:
  1637. ;;
  1638. ;;    void DPMIGetFreeMemory(
  1639. ;;        struct freeMem_t *freeMem); ;; receives free mem info
  1640. ;;
  1641. ;;
  1642. ;; Description:
  1643. ;;
  1644. ;;    This function retrieves free memory information from the DPMI
  1645. ;;    host.  The freeMem argument is a pointer to the structure to
  1646. ;;    receive the free memory information. Only the first field
  1647. ;;    (largestFree) of the free memory structure is guaranteed to be
  1648. ;;    supported.  The other values are set to 0xffffffff if the 
  1649. ;;    item is unavailable.
  1650. ;;
  1651. ;; DPMI reference: INT 31h AX=0500h
  1652.  
  1653. DPMIGetFreeMemory PROC C USES DI,    \
  1654.     freeMem:PTR
  1655.  
  1656.     mov    ax, 0500h
  1657.     ldptr    di, freeMem, es
  1658.     int    31h
  1659.     ret
  1660. DPMIGetFreeMemory ENDP
  1661.  
  1662. ;;======================================================================
  1663. ;; Function: Allocate Memory Block
  1664. ;;
  1665. ;; Synopsis:
  1666. ;;
  1667. ;;    int DPMIAllocateMemory(
  1668. ;;        uLong nBytes,        ;; size of block to allocate
  1669. ;;        uLong *base,        ;; receives linear base of block
  1670. ;;        uLong *handle);        ;; receives block handle
  1671. ;;
  1672. ;; Description:
  1673. ;;
  1674. ;;    This function allocates a memory block.  The nBytes argument
  1675. ;;    specifies the desired size of the block to allocate, in bytes.
  1676. ;;    The linear base address of the block that is allocated is 
  1677. ;;    written to the address pointed to by the base argument.  The
  1678. ;;    block handle is written to the address pointed to by the handle
  1679. ;;    argument.  The handle is used to free or resize the block.
  1680. ;;
  1681. ;; DPMI reference: INT 31h AX=0501h
  1682. ;;
  1683. ;; Version 1.0 Error returns:
  1684. ;;
  1685. ;;    8012h    linear memory unavailable
  1686. ;;    8013h    physicl memory unavailable
  1687. ;;    8014h    backing store unavailable
  1688. ;;    8016h    handle unavailable
  1689. ;;    8021h    invalid value
  1690.  
  1691. DPMIAllocateMemory PROC C USES SI DI,    \
  1692.     nBytes:uLong,            \
  1693.     base:PTR,            \
  1694.     handle:PTR
  1695.  
  1696.     mov    ax, 0501h
  1697.     ldlong    bx, cx, nBytes
  1698.     int    31h
  1699.     jc    @@exit
  1700.  
  1701.     mov    ax, bx
  1702.     ldptr    bx, base
  1703.     stlong    [bx], ax, cx
  1704.     ldptr    bx, handle
  1705.     stlong    [bx], si, di
  1706.     xor    ax, ax
  1707. @@exit:
  1708.     ret
  1709. DPMIAllocateMemory ENDP
  1710.  
  1711. ;;======================================================================
  1712. ;; Function: Free Memory Block
  1713. ;;
  1714. ;; Synopsis:
  1715. ;;
  1716. ;;    int DPMIFreeMemory(
  1717. ;;        uLong handle);        ;; handle of block to free
  1718. ;;
  1719. ;;
  1720. ;; Description:
  1721. ;;
  1722. ;;    This function frees a memory block allocated by DPMIAllocateMemory.
  1723. ;;
  1724. ;; DPMI reference: INT 31h AX=0502h
  1725. ;;
  1726. ;; Version 1.0 Error returns:
  1727. ;;
  1728. ;;    8023h    invalid handle
  1729.  
  1730. DPMIFreeMemory PROC C USES SI DI,    \
  1731.     handle:uLong
  1732.  
  1733.     mov    ax, 0502h
  1734.     ldlong    si, di, handle
  1735.     int    31h
  1736.     jc    @@exit
  1737.     xor    ax, ax
  1738. @@exit:
  1739.     ret
  1740. DPMIFreeMemory ENDP
  1741.  
  1742. ;;======================================================================
  1743. ;; Function: Resize Memory Block
  1744. ;;
  1745. ;; Synopsis:
  1746. ;;
  1747. ;;    int DPMIResizeMemory(
  1748. ;;        uLong *handle,        ;;address of handle of block to resize
  1749. ;;        uLong nBytes,        ;; new desired size in bytes
  1750. ;;        uLong *base);        ;; receives new linear base of block
  1751. ;;
  1752. ;; Description:
  1753. ;;
  1754. ;;    This function resizes a memory block allocated by DPMIAllocateMemory.
  1755. ;;    The handle argument points to the handle of the block to resize.
  1756. ;;    The nBytes argument is the desired new size of the block, in bytes.
  1757. ;;    The base argument points to the address to receive the new address
  1758. ;;    of the block.  Note that both the block handle and the linear base
  1759. ;;    of the block may be changed by this call.
  1760. ;;
  1761. ;; DPMI reference: INT 31h AX=0503h
  1762. ;;
  1763. ;; Version 1.0 Error returns:
  1764. ;;
  1765. ;;    8012h    linear memory unavailable
  1766. ;;    8013h    physical memory unavailable
  1767. ;;    8014h    backing store unavailable
  1768. ;;    8016h    handle unavailable
  1769. ;;    8021h    invalid value
  1770.  
  1771. DPMIResizeMemory PROC C USES SI DI,    \
  1772.     handle:PTR,            \
  1773.     nBytes:uLong,            \
  1774.     base:PTR
  1775.  
  1776.     mov    ax, 0503h
  1777.     ldptr    bx, handle
  1778.     ldlong    si, di, [bx]
  1779.     ldlong    bx, cx, nBytes
  1780.     int    31h
  1781.     jc    @@exit
  1782.  
  1783.     mov    ax, bx
  1784.     ldptr    bx, base
  1785.     stlong    [bx], ax, cx
  1786.     ldptr    bx, handle
  1787.     stlong    [bx], si, di
  1788.     xor    ax, ax
  1789. @@exit:
  1790.     ret
  1791. DPMIResizeMemory ENDP
  1792.  
  1793. ;;======================================================================
  1794. ;; Function: Lock Linear Region of Memory
  1795. ;;
  1796. ;; Synopsis:
  1797. ;;
  1798. ;;    int DPMILockRegion(
  1799. ;;        uLong base,        ;; linear address of region to lock
  1800. ;;        uLong nBytes);        ;; size of region to lock
  1801. ;;
  1802. ;; Description:
  1803. ;;
  1804. ;;    This function is used to prevent pages from being swapped to disk
  1805. ;;    by a DPMI host that supports virtual memory.  The base argument is
  1806. ;;    the linear address of the start of the region to be locked, and the
  1807. ;;    nBytes argument is the size of the region to lock.  The host maintains
  1808. ;;    a lock count for each page.  If the DPMI host does not support 
  1809. ;;    virtual memory, the function has no effect.
  1810. ;;
  1811. ;; DPMI reference: INT 31h AX=0600h
  1812. ;;
  1813. ;; Version 1.0 Error returns:
  1814. ;;
  1815. ;;    8013h    physical memory unavailable
  1816. ;;    8017h    lock count exceeded
  1817. ;;    8025h    invalid linear address
  1818.  
  1819. DPMILockRegion PROC C USES SI DI,    \
  1820.     base:uLong,            \
  1821.     nBytes:uLong
  1822.  
  1823.     mov    ax, 0600h
  1824.     ldlong    bx, cx, base
  1825.     ldlong    si, di, nBytes
  1826.     int    31h
  1827.     jc    @@exit
  1828.     xor    ax, ax
  1829. @@exit:
  1830.     ret
  1831. DPMILockRegion ENDP
  1832.  
  1833. ;;======================================================================
  1834. ;; Function: Unlock Linear Region of Memory
  1835. ;;
  1836. ;; Synopsis:
  1837. ;;
  1838. ;;    int DPMIUnlockRegion(
  1839. ;;        uLong base,        ;; linear address of region to unlock
  1840. ;;        uLong nBytes);        ;; size of region to unlock
  1841. ;;
  1842. ;; Description:
  1843. ;;
  1844. ;;    This function decrements the lock count for pages in the specified
  1845. ;;    region.  The base argument is the linear address of the start of the
  1846. ;;    region, and the nBytes argument is the size of the region in bytes.
  1847. ;;    Pages are not unlocked until the lock count is zero.
  1848. ;;
  1849. ;; DPMI reference: INT 31h AX=0601h
  1850. ;;
  1851. ;; Version 1.0 Error returns:
  1852. ;;
  1853. ;;    8002h    invalid state
  1854. ;;    8025h    invalid linear address
  1855.  
  1856. DPMIUnlockRegion PROC C USES SI DI,    \
  1857.     base:uLong,            \
  1858.     nBytes:uLong
  1859.  
  1860.     mov    ax, 0601h
  1861.     ldlong    bx, cx, base
  1862.     ldlong    si, di, nBytes
  1863.     int    31h
  1864.     jc    @@exit
  1865.     xor    ax, ax
  1866. @@exit:
  1867.     ret
  1868. DPMIUnlockRegion ENDP
  1869.  
  1870. ;;======================================================================
  1871. ;; Function: Mark Real Mode Region as Pageable
  1872. ;;
  1873. ;; Synopsis:
  1874. ;;
  1875. ;;    int DPMIMarkRealRegionPageable(
  1876. ;;        uLong base,        ;; linear address of region to mark
  1877. ;;        uLong nBytes);        ;; size in bytes of region to mark
  1878. ;;
  1879. ;; Description:
  1880. ;;
  1881. ;;    This function allows memory in the low megabyte of the linear
  1882. ;;    address space to be swapped to disk by a DPMI host that supports
  1883. ;;    virtual memory.  The base argument is the linear address of the
  1884. ;;    start of the region to be made pageable, and the nBytes argument
  1885. ;;    is the size of the region in bytes. 
  1886. ;;
  1887. ;; DPMI reference: INT 31h AX=0602h
  1888. ;;
  1889. ;; Version 1.0 Error returns:
  1890. ;;
  1891. ;;    8002h    invalid state
  1892. ;;    8025h    invalid linear address
  1893.  
  1894. DPMIMarkRealRegionPageable PROC C USES SI DI,    \
  1895.     base:uLong,                \
  1896.     nBytes:uLong
  1897.  
  1898.     mov    ax, 0602h
  1899.     ldlong    bx, cx, base
  1900.     ldlong    si, di, nBytes
  1901.     int    31h
  1902.     jc    @@exit
  1903.     xor    ax, ax
  1904. @@exit:
  1905.     ret
  1906. DPMIMarkRealRegionPageable ENDP
  1907.  
  1908. ;;======================================================================
  1909. ;; Function: Relock Real Mode Region
  1910. ;;
  1911. ;; Synopsis:
  1912. ;;
  1913. ;;    int DPMIRelockRealRegion(
  1914. ;;        uLong base,        ;; linear address of region to relock
  1915. ;;        uLong nBytes);        ;; size in bytes of region to relock
  1916. ;;
  1917. ;; Description:
  1918. ;;
  1919. ;;    This function relocks a memory region in the low 1 MB that was marked
  1920. ;;    as pageable by DPMIMarkRealRegionPageable.  The base argument is the
  1921. ;;    linear address of the start of the region to be relocked, and the
  1922. ;;    nBytes argument is the size of the region in bytes. 
  1923. ;;
  1924. ;; DPMI reference: INT 31h AX=0603h
  1925. ;;
  1926. ;; Version 1.0 Error returns:
  1927. ;;
  1928. ;;    8002h    invalid state
  1929. ;;    8013h    physical meomory unavailable
  1930. ;;    8025h    invalid linear address
  1931.  
  1932. DPMIRelockRealRegion PROC C USES SI DI,    \
  1933.     base:uLong,            \
  1934.     nBytes:uLong
  1935.  
  1936.     mov    ax, 0603h
  1937.     ldlong    bx, cx, base
  1938.     ldlong    si, di, nBytes
  1939.     int    31h
  1940.     jc    @@exit
  1941.     xor    ax, ax
  1942. @@exit:
  1943.     ret
  1944. DPMIRelockRealRegion ENDP
  1945.  
  1946. ;;======================================================================
  1947. ;; Function: Get Size of Processor Page
  1948. ;;
  1949. ;; Synopsis:
  1950. ;;
  1951. ;;    int DPMIGetPageSize(
  1952. ;;        uLong *pageSize);
  1953. ;;
  1954. ;; Description:
  1955. ;;
  1956. ;;    This function is used to determine the processor's page size.
  1957. ;;    The pageSize argument points to the location to receive the
  1958. ;;    page size, in bytes.  16-bit hosts will fail this call.
  1959. ;;
  1960. ;; DPMI reference: INT 31h AX=0604h
  1961. ;;
  1962. ;; Version 1.0 Error returns:
  1963. ;;
  1964. ;;    8001h    unsupported function
  1965.  
  1966. DPMIGetPageSize PROC C \
  1967.     pageSize:PTR
  1968.  
  1969.     mov    ax, 0604h
  1970.     int    31h
  1971.     jc    @@exit
  1972.  
  1973.     mov    ax, bx
  1974.     ldptr    bx, pageSize
  1975.     stlong    [bx], ax, cx
  1976.     xor    ax, ax
  1977. @@exit:
  1978.     ret
  1979. DPMIGetPageSize ENDP
  1980.  
  1981. ;;======================================================================
  1982. ;; Function: Nominate Pages as Demand Paging Candidates
  1983. ;;
  1984. ;; Synopsis:
  1985. ;;
  1986. ;;    int DPMINominatePages(
  1987. ;;        uLong base,        ;; base of region to nominate
  1988. ;;        uLong nBytes);        ;; size in bytes of region
  1989. ;;
  1990. ;; Description:
  1991. ;;
  1992. ;;    This function is used to indicate to the DPMI host that a range
  1993. ;;    of memory should be the most likely to be swapped to disk.  The
  1994. ;;    base argument is the linear address of the start of the region
  1995. ;;    to be nominated, and the nBytes argument is the size of the region,
  1996. ;;    in bytes.  The call is advisory only.
  1997. ;;
  1998. ;; DPMI reference: INT 31h AX=0702h
  1999. ;;
  2000. ;; Version 1.0 Error returns:
  2001. ;;
  2002. ;;    8025h    invalid linear address range
  2003.  
  2004. DPMINominatePages PROC C USES SI DI,    \
  2005.     base:uLong,            \
  2006.     nBytes:uLong
  2007.  
  2008.     mov    ax, 0702h
  2009.     ldlong    bx, cx, base
  2010.     ldlong    si, di, nBytes
  2011.     int    31h
  2012.     jc    @@exit
  2013.     xor    ax, ax
  2014. @@exit:
  2015.     ret
  2016. DPMINominatePages ENDP
  2017.  
  2018. ;;======================================================================
  2019. ;; Function: Discard Contents of Pages
  2020. ;;
  2021. ;; Synopsis:
  2022. ;;
  2023. ;;    int DPMIDiscardPageContents(
  2024. ;;        uLong base,        ;; base of region to discard
  2025. ;;        uLong nBytes);        ;; size of region in bytes
  2026. ;;
  2027. ;; Description:
  2028. ;;
  2029. ;;    This function advises the DPMI host to discard the contents of
  2030. ;;    the specified region to avoid unnecessarily saving them on disk.  The
  2031. ;;    base argument is the linear address of the start of the region
  2032. ;;    to be discarded, and the nBytes argument is the size of the region,
  2033. ;;    in bytes.  The call is advisory only.
  2034. ;;
  2035. ;; DPMI reference: INT 31h AX=0703h
  2036. ;;
  2037. ;; Version 1.0 Error returns:
  2038. ;;
  2039. ;;    8025h    invalid linear address
  2040.  
  2041. DPMIDiscardPageContents PROC C USES SI DI,      \
  2042.     base:uLong,                \
  2043.     nBytes:uLong
  2044.  
  2045.     mov    ax, 0703h
  2046.     ldlong    bx, cx, base
  2047.     ldlong    si, di, nBytes
  2048.     int    31h
  2049.     jc    @@exit
  2050.     xor    ax, ax
  2051. @@exit:
  2052.     ret
  2053. DPMIDiscardPageContents ENDP
  2054.  
  2055. ;;======================================================================
  2056. ;; Function: Get Linear Address for Physical Region 
  2057. ;;
  2058. ;; Synopsis:
  2059. ;;
  2060. ;;    int DPMIMapPhysicalRegion(
  2061. ;;        uLong physAddr,        ;; physical address to map
  2062. ;;        uLong nBytes,        ;; size of region to map
  2063. ;;        uLong *linear);        ;; receives linear address of region
  2064. ;;
  2065. ;; Description:
  2066. ;;
  2067. ;;    This function allows a DPMI client to obtain a linear address that
  2068. ;;    maps to any physical address above 1 MB.  The physAddr argument
  2069. ;;    specifies the physical address of the region to map. The nBytes
  2070. ;;    argument is the size of the region to map, in bytes. The linear
  2071. ;;    argument points to the address to receive the linear address that
  2072. ;;    the DPMI sets up to map the physical region.
  2073. ;;
  2074. ;; DPMI reference: INT 31h AX=0800h
  2075. ;;
  2076. ;; Version 1.0 Error returns:
  2077. ;;
  2078. ;;    8003h    system integrity
  2079. ;;    8021h    invalid value
  2080.  
  2081. DPMIMapPhysicalRegion PROC C USES SI DI,\
  2082.     physAddr:uLong,            \
  2083.     nBytes:uLong,            \
  2084.     linear:PTR
  2085.  
  2086.     mov    ax, 0800h
  2087.     ldlong    bx, cx, physAddr
  2088.     ldlong    si, di, nBytes
  2089.     int    31h
  2090.     jc    @@exit
  2091.  
  2092.     ldptr    si, linear
  2093.     stlong    [si], bx, cx
  2094.     xor    ax, ax
  2095. @@exit:
  2096.     ret
  2097. DPMIMapPhysicalRegion ENDP
  2098.  
  2099. ;;======================================================================
  2100. ;; Function: Test Virtual Interrupt State and Disable
  2101. ;;
  2102. ;; Synopsis:
  2103. ;;
  2104. ;;    int DPMITestDisableInts(void);
  2105. ;;
  2106. ;; Description:
  2107. ;;
  2108. ;;    This function returns the current virtual interrupt enable state,
  2109. ;;    and disables virtual interrupts.  The return value is zero if 
  2110. ;;    interrupts were previously disabled, and one if they were enabled.
  2111. ;;
  2112. ;; DPMI reference: INT 31h AX=0900h
  2113.  
  2114. DPMITestDisableInts PROC C
  2115.     mov    ax, 0900h
  2116.     int    31h
  2117.     xor    ah, ah
  2118.     ret
  2119. DPMITestDisableInts ENDP
  2120.  
  2121. ;;======================================================================
  2122. ;; Function: Test Virtual Interrupt State and Enable
  2123. ;;
  2124. ;; Synopsis:
  2125. ;;
  2126. ;;    int DPMITestEnableInts(void);
  2127. ;;
  2128. ;; Description:
  2129. ;;
  2130. ;;    This function returns the current virtual interrupt enable state,
  2131. ;;    and enables virtual interrupts.  The return value is zero if 
  2132. ;;    interrupts were previously disabled, and one if they were enabled.
  2133. ;;
  2134. ;; DPMI reference: INT 31h AX=0901h
  2135.  
  2136. DPMITestEnableInts PROC C
  2137.     mov    ax, 0901h
  2138.     int    31h
  2139.     xor    ah, ah
  2140.     ret
  2141. DPMITestEnableInts ENDP
  2142.  
  2143. ;;======================================================================
  2144. ;; Function: Test Virtual Interrupt State 
  2145. ;;
  2146. ;; Synopsis:
  2147. ;;
  2148. ;;    int DPMITestInts(void);
  2149. ;;
  2150. ;; Description:
  2151. ;;
  2152. ;;    This function returns the current virtual interrupt enable state.
  2153. ;;    The return value is zero if interrupts are disabled, and one if 
  2154. ;;    they are enabled.
  2155. ;;
  2156. ;;
  2157. ;; DPMI reference: INT 31h AX=0902h
  2158.  
  2159. DPMITestInts PROC C
  2160.     mov    ax, 0902h
  2161.     int    31h
  2162.     xor    ah, ah
  2163.     ret
  2164. DPMITestInts ENDP
  2165.  
  2166. ;;======================================================================
  2167. ;; Function: Get Vendor Extensions Entry Point
  2168. ;;
  2169. ;; Synopsis:
  2170. ;;
  2171. ;;    int DPMIGetVendorEntryPoint(
  2172. ;;        char *extensionID,
  2173. ;;        void (far* *extAPIEntry)());
  2174. ;;
  2175. ;; Description:
  2176. ;;    
  2177. ;;    This function retrieves an address that can be used to access
  2178. ;;    vendor specific DPMI extensions.  The extensionID argument points
  2179. ;;    to a null terminated string that identifies the desired set of
  2180. ;;    extensions.  The extAPIEntry argument points to the address where
  2181. ;;    a far pointer to the vendor entry point is to be stored.  The function
  2182. ;;    returns non-zero if the requested vendor extensions are not found.
  2183. ;;
  2184. ;; DPMI reference: INT 31h AX=0A00h and INT 2Fh AX=168Ah
  2185. ;;
  2186. ;; Version 1.0 Error returns:
  2187. ;;
  2188. ;;    8001h    unsupported function
  2189.  
  2190. DPMIGetVendorEntryPoint PROC C USES SI DI,    \
  2191.     extensionID:PTR,            \
  2192.     extAPIEntry:PTR
  2193.  
  2194.     mov    ax, 0A00h
  2195.     ldptr    si, extensionID
  2196.     int    31h
  2197.     jc    @@exit
  2198.  
  2199.     ldptr    bx, extAPIEntry
  2200.     stlong    [bx], es, di
  2201.     xor    ax, ax
  2202. @@exit:
  2203.     ret
  2204. DPMIGetVendorEntryPoint ENDP
  2205.  
  2206. ;;======================================================================
  2207. ;; Function: Set Debug Watchpoint
  2208. ;;
  2209. ;; Synopsis:
  2210. ;;
  2211. ;;    int DPMISetWatchpoint(
  2212. ;;        uLong linear,        ;; linear address of watchpoint
  2213. ;;        enum watchSize size,    ;; watchpoint size
  2214. ;;        enum watchType type,    ;; watchpoint type
  2215. ;;        uShort *watchHandle);    ;; receives watchpoint handle
  2216. ;;
  2217. ;; Description:
  2218. ;;
  2219. ;;    This function sets a debug watchpoint using the processor's debug
  2220. ;;    registers.  The linear argument specifies the linear address of the
  2221. ;;    watchpoint.  Arguments watchSize and watchType specify the size
  2222. ;;    and type of the watchpoint.  The watchHandle argument points to the
  2223. ;;    location to receive the watchpoint handle allocated by the DPMI
  2224. ;;    host.  Tripping a watchpoint invokes the exception 1 handler.
  2225. ;;
  2226. ;; DPMI reference: INT 31h AX=0B00h
  2227. ;;
  2228. ;; Version 1.0 Error returns:
  2229. ;;
  2230. ;;    8016h    too many breakpoints
  2231. ;;    8021h    invalid value
  2232. ;;    8025h    invalid linear address
  2233.  
  2234. DPMISetWatchpoint PROC C \
  2235.     linear:uLong,    \
  2236.     wSize:BYTE,    \
  2237.     wType:BYTE,    \
  2238.     watchHandle:PTR
  2239.  
  2240.     mov    ax, 0B00h
  2241.     ldlong    bx, cx, linear
  2242.     mov    dl, wSize
  2243.     mov    dh, wType
  2244.     int    31h
  2245.     jc    @@exit
  2246.     mov    ax, bx
  2247.     ldptr    bx, watchHandle
  2248.     mov    [bx], ax
  2249.     xor    ax, ax
  2250. @@exit:
  2251.     ret
  2252. DPMISetWatchpoint ENDP
  2253.  
  2254. ;;======================================================================
  2255. ;; Function: Clear Debug Watchpoint
  2256. ;;
  2257. ;; Synopsis:
  2258. ;;
  2259. ;;    int DPMIClearWatchpoint(
  2260. ;;        uShort watchHandle);    ;; handle of watchpoint to free
  2261. ;;
  2262. ;; Description:
  2263. ;;
  2264. ;;    This function releases the watchpoint handle allocated by
  2265. ;;    DPMISetWatchpoint, and clears the associated debug register.
  2266. ;;    The watchHandle argument is the handle of the watchpoint to free.
  2267. ;;
  2268. ;; DPMI reference: INT 31h AX=0B01h
  2269. ;;
  2270. ;; Version 1.0 Error returns:
  2271. ;;
  2272. ;;    8023h    invalid handle
  2273.  
  2274. DPMIClearWatchpoint PROC C    \
  2275.     watchHandle:uShort
  2276.  
  2277.     mov    ax, 0B01h
  2278.     mov    bx, watchHandle
  2279.     int    31h
  2280.     jc    @@exit
  2281.     xor    ax, ax
  2282. @@exit:
  2283.     ret
  2284. DPMIClearWatchpoint ENDP
  2285.  
  2286. ;;======================================================================
  2287. ;; Function: Get Debug Watchpoint State
  2288. ;;
  2289. ;; Synopsis:
  2290. ;;
  2291. ;;    int DPMIGetWatchpointState(
  2292. ;;        uShort watchHandle,    ;;handle of watchpoint to get state of
  2293. ;;        uChar *tripped);    ;; receives state
  2294. ;;
  2295. ;; Description:
  2296. ;;
  2297. ;;    This function retrieves the state of a watchpoint set by 
  2298. ;;    DPMISetWatchpoint.  The watchHandle argument is the handle of
  2299. ;;    watchpoint whose state is to be retrieved.  The tripped argument
  2300. ;;    receives a zero if the watchpoint has not been encountered,
  2301. ;;    and receives a one if the watchpoint has been encountered.
  2302. ;;
  2303. ;; DPMI reference: INT 31h AX=0B02h
  2304. ;;
  2305. ;; Version 1.0 Error returns:
  2306. ;;
  2307. ;;    8023h    invalid handle
  2308.  
  2309. DPMIGetWatchpointState PROC C    \
  2310.     watchHandle:uShort,    \
  2311.     tripped:PTR
  2312.  
  2313.     mov    ax, 0B02h
  2314.     mov    bx, watchHandle
  2315.     int    31h
  2316.     jc    @@exit
  2317.     ldptr    bx, tripped
  2318.     mov    [bx], al
  2319.     xor    ax, ax
  2320. @@exit:
  2321.     ret
  2322. DPMIGetWatchpointState ENDP
  2323.  
  2324. ;;======================================================================
  2325. ;; Function: Reset Debug Watchpoint
  2326. ;;
  2327. ;; Synopsis:
  2328. ;;
  2329. ;;    int DPMIResetWatchpoint(
  2330. ;;        uShort watchHandle);    ;; handle of watchpoint to reset
  2331. ;;
  2332. ;; Description:
  2333. ;;
  2334. ;;    This function resets the state of a watchpoint allocated by
  2335. ;;    DPMISetWatchpoint.  This sets the watchpoint state to 
  2336. ;;    "not encountered".  The watchHandle argument specifies the watchpoint
  2337. ;;    in question.
  2338. ;;
  2339. ;; DPMI reference: INT 31h AX=0B03h
  2340. ;;
  2341. ;; Version 1.0 Error returns:
  2342. ;;
  2343. ;;    8023h    invalid handle
  2344.  
  2345. DPMIResetWatchpoint PROC C \
  2346.     watchHandle:uShort
  2347.  
  2348.     mov    ax, 0B03h
  2349.     mov    bx, watchHandle
  2350.     int    31h
  2351.     jc    @@exit
  2352.     xor    ax, ax
  2353. @@exit:
  2354.     ret
  2355. DPMIResetWatchpoint ENDP
  2356.  
  2357. ;;======================================================================
  2358. ;; Function: Get Current Code Segment
  2359. ;;
  2360. getCS    PROC C
  2361.     mov     ax, cs
  2362.     ret
  2363. getCS    ENDP
  2364.  
  2365. ;;======================================================================
  2366. ;; Function: Get Current Data Segment
  2367.  
  2368. getDS    PROC C
  2369.     mov     ax, ds
  2370.     ret
  2371. getDS    ENDP
  2372.  
  2373.  
  2374.  
  2375.  
  2376. ;;======================================================================
  2377. ;; 
  2378. ;; The remainder of the source module is comprised of routines that
  2379. ;; re-fix-up the EXE after entering protected mode
  2380. ;;
  2381.  
  2382. relocCountOffset     equ     6
  2383. relocTableStart     equ     18h
  2384.  
  2385. ;;======================================================================
  2386. ;; Read a word from a file
  2387. ;;   bx is the handle
  2388. ;;   ax is the offset
  2389. ;;
  2390. ;;   Return word in ax
  2391. ;;
  2392. getWord    PROC C USES DS BX CX DX
  2393.     mov    dx, ax
  2394.     mov    ax, 4200h
  2395.     xor    cx, cx
  2396.     int    21h            ;; seek to offset
  2397.     push    ax
  2398.     mov    dx, sp
  2399.     push    ss
  2400.     pop    ds
  2401.     mov    cx, 2
  2402.     mov    ah, 3fh
  2403.     int    21h            ;; read to word buf on stack
  2404.     pop    ax            ;; pop word for return
  2405.     ret
  2406. getWord ENDP
  2407.  
  2408. ;;======================================================================
  2409. ;;Read in the fixup table
  2410. ;; 
  2411. readFixupTable PROC
  2412.     mov    ah, 62h            ;; get psp
  2413.     int    21h
  2414.     mov    es, bx
  2415.     mov    es, es:[2ch]        ;; get environment
  2416.     xor    bx, bx
  2417. chkForEnd:
  2418.     cmp    word ptr es:[bx], 0
  2419.     je    foundEnvEnd
  2420.     inc    bx
  2421.     jmp    chkForEnd
  2422. foundEnvEnd:
  2423.     add    bx, 4
  2424.     push    ds
  2425.     push    es
  2426.     pop    ds
  2427.     mov    dx, bx
  2428.     mov    ax, 3d00h        ;; open this exe file
  2429.     int    21h
  2430.     pop    ds
  2431.     jc    rFTfail
  2432.     mov    bx, ax            ;; handle to bx
  2433.  
  2434.     mov    ax, 0
  2435.     call    getWord
  2436.     cmp    ax, 'ZM'        ;; quit if not exe signature
  2437.     push    ax
  2438.     jne    rFTclose
  2439.     pop    ax
  2440.  
  2441.     mov    ax, relocCountOffset
  2442.     call    getWord            ;; get reloc count to cx
  2443.     mov    cx, ax
  2444.  
  2445.     or    cx, cx
  2446.     jnz    getTable
  2447.     push    cx
  2448.     jmp    rFTclose
  2449.  
  2450. getTable:
  2451.     mov    ax, relocTableStart
  2452.     call    getWord            ;; get start of reloc table
  2453.  
  2454.     push    cx            ;; save count
  2455.     xor    cx, cx
  2456.     mov    dx, ax
  2457.     mov    ax, 4200h        ;; seek to reloc table
  2458.     int    21h
  2459.     pop    cx
  2460.     jc    rFTfail
  2461.  
  2462.     shl    cx, 2            ;; each entry four bytes
  2463.     add    cx, 0fh            ;; round up to para
  2464.     shr    cx, 4            ;; cx = paras needed for table
  2465.  
  2466.     push    cx            ;; save para count
  2467.     push    bx            ;; save handle
  2468.     mov    bx, cx            ;; get a buffer from DOS
  2469.     mov    ah, 48h
  2470.     int    21h
  2471.     pop    bx
  2472.     pop    cx
  2473.     jc    rFTfail
  2474.     
  2475.     push    ds
  2476.     mov    ds, ax
  2477.     mov    es, ax            ;; es is para of table
  2478.     xor    dx, dx
  2479.     shl    cx, 4            ;; para to byte
  2480.     mov    ah, 3fh
  2481.     int    21h            ;; read reloc table
  2482.     pop    ds
  2483.     jc    rFTfail
  2484.  
  2485.     mov    ax, relocCountOffset
  2486.     call    getWord
  2487.     push    ax
  2488.  
  2489. rFTclose:
  2490.     mov    ah, 3eh
  2491.     int    21h            ;; close the file
  2492.     pop    ax            ;; pop count of relocs
  2493.     jmp    short rFTexit
  2494.  
  2495. rFTfail:
  2496.     xor    ax, ax
  2497. rFTexit:
  2498.     ret
  2499. readFixupTable ENDP
  2500.  
  2501.  
  2502. ;;======================================================================
  2503. ;; Initialize the fixup data area
  2504. ;;
  2505. setupFixup PROC C USES AX BX CX DX
  2506.     mov    ax, 0000h        ;; get a descriptor
  2507.     int    31h
  2508.     mov    fixupSel, ax
  2509.  
  2510.     mov    dx, 0ffffh
  2511.     mov    cx, 0
  2512.     mov    bx, ax
  2513.     mov    ax, 0008h        ;; set limit to 64 kb
  2514.     int    31h
  2515.  
  2516.     mov    ax, 0006h        ;; get segment base
  2517.     mov    bx, cs
  2518.     int    31h
  2519.     shr    dx, 4            ;; convert linear base to para
  2520.     shl    cx, 12
  2521.     or    dx, cx
  2522.     mov    codePara, dx
  2523.  
  2524.     mov    ax, 0006h        ;; get segment base
  2525.     mov    bx, ds
  2526.     int    31h
  2527.     shr    dx, 4            ;; convert linear base to para
  2528.     shl    cx, 12
  2529.     or    dx, cx
  2530.     mov    dataPara, dx
  2531.  
  2532.     ret
  2533. setupFixup ENDP
  2534.  
  2535. ;;======================================================================
  2536. ;; Process a fixup
  2537. ;;
  2538. ;; es:di points to fixup record
  2539. ;;
  2540. processFixup PROC USES CX ES
  2541.     mov    bx, es:[di]        ;; pick up fixup rec in ax bx
  2542.     mov    dx, es:[di].2        
  2543.     add    dx, codePara
  2544.     mov    ax, dx            ;; compute linear address
  2545.     shl    ax, 4
  2546.     shr    dx, 12
  2547.     add    ax, bx
  2548.     adc    dx, 0            ;; linear addr of fixup in dx:ax
  2549.     mov    bx, fixupSel
  2550.     mov    cx, dx
  2551.     mov    dx, ax
  2552.     mov    ax, 7            ;; target descriptor to fixup
  2553.     int    31h
  2554.     mov    es, bx
  2555.     mov    ax, es:[0]        ;; get fixup target
  2556.     cmp    ax, codePara        ;; is it a fixup to CS?
  2557.     je    fixCode
  2558.     cmp    ax, dataPara        ;; a fixup to DS?
  2559.     jb    newCode
  2560.     je    fixData
  2561.     jmp    newData
  2562.  
  2563. fixCode:
  2564.     mov    es:[0], cs
  2565.     jmp    pFexit
  2566.  
  2567. fixData:
  2568.     mov    es:[0], ds
  2569.     jmp    pFexit
  2570.  
  2571. newCode:
  2572.     mov    bx, ax            ;; para to selector
  2573.     mov    ax, 0002h
  2574.     int    31h
  2575.  
  2576.     mov    bx, ax            ;; create an alias
  2577.     mov    ax, 0ah
  2578.     int    31h
  2579.  
  2580.     mov    bx, ax            ;; set arb to code
  2581.     lar    cx, ax
  2582.     shr    cx, 8
  2583.     or    cx, 8
  2584.  
  2585.     mov    ax, 9
  2586.     int    31h
  2587.  
  2588.     mov    es:[0], bx
  2589.     jmp    pFexit
  2590.  
  2591. newData:
  2592.     mov    bx, ax            ;; para to selector
  2593.     mov    ax, 0002h
  2594.     int    31h
  2595.     mov    es:[0], ax
  2596.     jmp    pFexit
  2597.  
  2598. pFexit:
  2599.     ret
  2600. processFixup ENDP
  2601.  
  2602.  
  2603. ;;======================================================================
  2604. ;; Main routine for fixup
  2605. ;;
  2606. ;;
  2607. _fixup    PROC C  USES DI
  2608.     call    readFixupTable        ;; rets count in ax, table in es
  2609.     or    ax, ax
  2610.     jz    fixupExit
  2611.  
  2612.     call    setupFixup
  2613.  
  2614.     mov    cx, ax
  2615.     xor     di, di
  2616. nextFU:
  2617.     call    processFixup
  2618.     add    di, 4
  2619.     loop    nextFU
  2620.  
  2621.     mov    ax, 1            ;; free descriptor
  2622.     mov    bx, fixupSel
  2623.     int    31h
  2624.  
  2625.     mov    ah, 49h
  2626.     int    21h
  2627. fixupExit:
  2628.     ret
  2629. _fixup    ENDP
  2630.  
  2631. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2632. ;;;         Exception handlers
  2633. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2634. ;;
  2635. ;; Macro to output a string
  2636. puts     MACRO str
  2637.     local over, slbl
  2638.     jmp    short over
  2639. slbl    db    str, '$'
  2640. over:
  2641.     lea    dx, slbl
  2642.     mov    ah, 9
  2643.     int    21h
  2644.     ENDM
  2645.  
  2646. ;; Macro to output a hex value 
  2647. hexOut    MACRO val
  2648.     mov    cx, val
  2649.     call    putHex
  2650.     ENDM
  2651.  
  2652. ;; Macro to output a string followed by a hex value
  2653. putReg    MACRO str, r
  2654.     puts    str
  2655.     mov    cx, r
  2656.     call    putHex
  2657.     ENDM
  2658.  
  2659. ;; Hex output routine
  2660. hexdigs    db "0123456789ABCDEF"
  2661. putHex    PROC USES BX             ;; output CX in hex
  2662.     mov    bx, cx            ;;   use bx as working reg
  2663.     shr    bx, 12            ;;   top nibble to right
  2664.     mov    dl, hexdigs[bx]        ;;   look up character
  2665.     mov    ah, 2            ;;   send to DOS
  2666.     int    21h
  2667.  
  2668.     mov    bx, cx            ;; original value to bx
  2669.     shr    bx, 8            ;; 2nd nibble to right
  2670.     and    bx, 0fh            ;; mask off unwanted higher nibble
  2671.     mov    dl, hexdigs[bx]        ;; look up character
  2672.     mov    ah, 2            ;; send to DOS
  2673.     int    21h
  2674.  
  2675.     mov    bx, cx            ;; etc.
  2676.     shr    bx, 4
  2677.     and    bx, 0fh
  2678.     mov    dl, hexdigs[bx]
  2679.     mov    ah, 2
  2680.     int    21h
  2681.  
  2682.     mov    bx, cx
  2683.     and    bx, 0fh
  2684.     mov    dl, hexdigs[bx]
  2685.     mov    ah, 2
  2686.     int    21h
  2687.     
  2688.     ret
  2689. putHex    ENDP
  2690.  
  2691. ;; Exception handler entry points
  2692. ;;
  2693. ;; This macro generates the exception handlers, each of which pushes
  2694. ;; its ordinal value and jumps to the generic handler
  2695. ;;
  2696.     IRP n, <00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F>
  2697. _exc&n&Handler:
  2698.     push    &n&H
  2699.     jmp    near ptr exceptionEntry
  2700.     ENDM
  2701. ;; 
  2702. ;; Exception names - the generic handler uses this table to look up
  2703. ;; the name of the exception that occurred
  2704. ;;
  2705. x00nm    db    "Divide by Zero$"
  2706. x01nm    db    "Trace$"
  2707. x02nm    db    "?$"
  2708. x03nm    db    "Breakpoint$"
  2709. x04nm    db    "Overflow$"
  2710. x05nm    db    "Bounds$"
  2711. x06nm    db    "Invalid Opcode$"
  2712. x07nm    db    "Coprocessor (7)$"
  2713. x08nm    db    "Double Fault$"
  2714. x09nm    db    "Coprocessor (9)$"
  2715. x0anm    db    "Invalid TSS$"
  2716. x0bnm    db    "Segment not present$"
  2717. x0cnm    db    "Stack$"
  2718. x0dnm    db    "General Protection$"
  2719. x0enm    db    "Page Fault$"
  2720. x0fnm    db    "?$"
  2721. x10nm    db    "Coprocessor (16)$"
  2722.  
  2723. xNameTable:
  2724.     IRP n, <00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F>
  2725.     dw    offset x&n&nm
  2726.     ENDM
  2727.  
  2728. ;;
  2729. ;; Exception entry point table - this table contains the offset of each
  2730. ;; handler - used to hook the vectors.
  2731. ;;
  2732. xEntryTable:
  2733.     IRP n, <00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F>
  2734.     dw    offset _exc&n&Handler
  2735.     ENDM
  2736.  
  2737. ;;
  2738. ;; Install the default exception handlers for fatal exceptions
  2739. ;;
  2740. _installHandlers PROC USES SI DI
  2741.     lea    si, xEntryTable
  2742.     xor    di, di
  2743. _iHhook:
  2744.     IRP n, <0, 1, 2, 3, 4, 5, 7>    ;; don't handle these - DPMI is
  2745.       cmp    di, n            ;; supposed to pass them through
  2746.       je    _iHnext            ;; to real mode
  2747.     ENDM
  2748.  
  2749.     mov    ax, 203h        ;; set exception handler service
  2750.     mov    bx, di
  2751.     mov    cx, cs
  2752.     mov    dx, cs:[si]
  2753.     int    31h
  2754.  
  2755. _iHnext:
  2756.     add    si, 2
  2757.     inc    di
  2758.     cmp    di, 10h
  2759.     jne    _iHhook
  2760.  
  2761.     ret
  2762. _installHandlers ENDP
  2763.  
  2764.  
  2765. ;; This structure defines the register structure in effect while the 
  2766. ;; generic handler runs
  2767. ;;
  2768. eFrame STRUC
  2769.     efDS    dw    ?
  2770.     efES    dw    ?
  2771.     efDI    dw    ?
  2772.     efSI    dw    ?
  2773.     efBP    dw    ?
  2774.     efXX    dw    ?
  2775.     efBX    dw    ?
  2776.     efDX    dw    ?
  2777.     efCX    dw    ?
  2778.     efAX    dw    ?
  2779.     efxNum    dw    ?
  2780.     efhRIP    dw    ?
  2781.     efhRCS    dw    ?
  2782.     efError    dw    ?
  2783.     efXIP    dw    ?
  2784.     efXCS    dw    ?
  2785.     efXFl    dw    ?
  2786.     efXSP    dw    ?
  2787.     efXSS    dw    ?
  2788. eFrame ENDS
  2789.  
  2790. ;;
  2791. ;; The generic handler - dump registers and exit
  2792. ;;
  2793. exceptionEntry PROC
  2794.     pusha                    ;; build frame
  2795.     push    es
  2796.     push    ds
  2797.     mov    bp, sp
  2798.  
  2799.     push    cs                ;; ds <- cs
  2800.     pop    ds
  2801.  
  2802.     mov    bx, [bp].efxNum            ;; get exception number
  2803.     shl    bx, 1                ;; make it word offset
  2804.     add    bx, offset xNameTable        ;; look up name of exception
  2805.     mov    dx, [bx]
  2806.  
  2807.     mov    ah, 9                ;; output it to  DOS
  2808.     int    21h
  2809.  
  2810.     putReg    " Exception at ", [bp].efXCS    ;; dump regs
  2811.     putReg    ":",efXIP
  2812.     putReg    " Error code=", [bp].efError
  2813.     puts    <10,13>
  2814.  
  2815.     putReg    "SS=", [bp].efXSS
  2816.     putReg    " SP=", [bp].efXSP
  2817.     putReg    " DS=", [bp].efDS
  2818.     putReg    " ES=", [bp].efES
  2819.     putReg    " Flags=", [bp].efXFl
  2820.  
  2821.     puts    <10,13>
  2822.     putReg    "AX=", [bp].efAX
  2823.     putReg    " BX=", [bp].efBX
  2824.     putReg    " CX=", [bp].efCX
  2825.     putReg    " DX=", [bp].efDX
  2826.     putReg    " SI=", [bp].efSI
  2827.     putReg    " DI=", [bp].efDI
  2828.     putReg    " BP=", [bp].efBP
  2829.     puts    <10,13>
  2830.  
  2831.     mov    [bp].efXCS, cs                ;; set frame to exit
  2832.     mov    [bp].efXIP, offset bye
  2833.     pop    ds
  2834.     pop    es
  2835.     popa
  2836.     add    sp, 2
  2837.     retf                        ;; get off host stack
  2838.  
  2839. bye:
  2840.     mov    ah, 4Ch                    ;; and terminate
  2841.     int    21h
  2842. exceptionEntry ENDP
  2843.  
  2844.     end
  2845.