home *** CD-ROM | disk | FTP | other *** search
/ DOS Wares / doswares.zip / doswares / UTILS / TOOLS / PERUSE.ZIP / PERASM.ZIP / PERUSEE.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-03-21  |  18.1 KB  |  539 lines

  1.             page    55,132
  2.             title   "PERUSEE = EMS interface for PERUSE"
  3.  
  4. ; ---------------------------------------------------------------------
  5. ;
  6. ; PERUSEE - EMS interface for PERUSE
  7. ; First Published in PC Magazine April 12, 1994
  8. ;
  9. ; ---------------------------------------------------------------------
  10.  
  11. ; ---------------------------------------------------------------------
  12. ; $lgb$
  13. ; 1.0      02/09/94      RVF      Final beta complete. Can release if
  14. ;                               + no other errors found.
  15. ; 1.1      03/21/94      RVF      Added proper mask when allocating
  16. ;                               + memory
  17. ; $lge$
  18. ; ---------------------------------------------------------------------
  19. ; $nokeywords$
  20.  
  21.  
  22. ; -----------------------------------------------------------------------
  23. ;
  24. ;   Buffer Memory Interface Routines
  25. ;
  26. ; -----------------------------------------------------------------------
  27.  
  28. ;   The folowing routines serve as the interface to the buffer memory.
  29. ;
  30. ;   All (or in this case, both) modules have the same inteface that
  31. ;   allows use of the buffer storage without the utilitie's specific
  32. ;   knowledge of what memory is in use.
  33. ;
  34. ;   Each module has a standard header that consists of the following:
  35. ;
  36. ;        2 byte length of module
  37. ;        1 byte module identifier (E = EMX, X = XMS)
  38. ;          Note: Must be upper case
  39. ;        JMP instrution to main entry point
  40. ;
  41. ;   Nothing is guaranteed beyond the header.
  42. ;
  43. ;   The module must be completely self contained, lying completely within
  44. ;   it's own segment. Any references within the segment must be relative
  45. ;   to that segment since PERUSE moves the module, in its entirety, to
  46. ;   another segment aligned address where it is actually executed.
  47. ;
  48.  
  49. ; -----------------------------------------------------------------------
  50. ;
  51. ;   Here are the specific calling sequences:
  52. ;
  53. ; -----------------------------------------------------------------------
  54.  
  55.  
  56. ;   General Return
  57. ;   --------------
  58. ;   If any error occurs, the function sets the carry flag.
  59. ;
  60. ;       carry flag = error
  61.  
  62.  
  63. ;   Initialize Scroll Memory
  64. ;   ------------------------
  65. ;   This call checks that the requested type of memory exists in
  66. ;   sufficient quantity to complete the call. If so, it allocates the
  67. ;   the memory and stores any information needed to access the memory.
  68. ;
  69. ;       ax = 00h
  70. ;       cx = number of 1k records needed
  71.  
  72.  
  73. ;   Read scroll record
  74. ;   ------------------
  75. ;   This function reads a record from the scroll buffer. If there are
  76. ;   n used records in the scroll buffer, the application may request
  77. ;   record numbers 0 to n-1. The contents of the record are placed in
  78. ;   the buffer located at es:dx.
  79. ;
  80. ;   The most recent record is considered record 0 and the oldest is n-1.
  81. ;
  82. ;       ax = 01h
  83. ;       bx = record number; where: 0=oldest record, n-1=most recent
  84. ;    es:di -> buffer
  85.  
  86.  
  87. ;   Write scroll record
  88. ;   -------------------
  89. ;   This function writes a new record to the scroll buffer. If the
  90. ;   scroll buffer has already filled, the oldest record is overwritten.
  91. ;
  92. ;       ax = 02h
  93. ;    ds:bx -> buffer to write
  94.  
  95.  
  96. ;   Get number of used records
  97. ;   --------------------------
  98. ;   This function returns the number of records used in the scroll buffer.
  99. ;
  100. ;       ax = 03h
  101. ;
  102. ;   returns:
  103. ;       ax = number of records used
  104.  
  105.  
  106. ;   Release scroll buffer
  107. ;   ---------------------
  108. ;   This function is called to release the scroll buffer before removing
  109. ;   the TSR from memory. If this function is not called, the scroll
  110. ;   buffer will not be released until the system is rebooted.
  111. ;
  112. ;       ax = 04h
  113.  
  114. ;   Save record pointer
  115. ;   -------------------
  116. ;   This function saves the current record information maintained by the
  117. ;   interface routine. Any future records written to the buffer can then
  118. ;   be "unsaved" by calling function 6.
  119. ;
  120. ;       ah = 05h
  121.  
  122. ;   Restore pointers
  123. ;   ----------------
  124. ;   This function restores the record pointers saved with function 5.
  125. ;   Furthermore, it clears any records written after the save.
  126. ;
  127. ;       ax = 06h
  128.  
  129. ; ----------------------------------------------------------------------
  130.  
  131. MaxFunction =       6                       ; Maximum function number
  132. RecSize     =       1024                    ; record size
  133.                           
  134.  
  135. ; ----------------------------------------------------------------------
  136. ;
  137. ;   EMS Interface Routine
  138. ;
  139. ; ----------------------------------------------------------------------
  140.  
  141.  
  142. EmsInt      segment para public 'code'      ; EMS interface
  143.             assume  cs:EmsInt               ; called via far call
  144.  
  145. EmsStart:
  146. EmsLen      dw      EmsEnd                  ; length of module
  147.             db      'E'                     ; module identifier
  148.  
  149.             jmp     short Ems               ; jump to dispatcher
  150.  
  151. Ems67v      equ     word ptr ds:[67h * 4]   ; offset for int 67h (EMS)
  152.  
  153. EmsSig      db      'EMMXXXX0'              ; EMS driver signature
  154.  
  155. EmsRecs     dw      0                       ; records allocated
  156. EmsUsed     dw      0                       ; records used
  157. EmsOld      dw      0                       ; oldest record
  158.  
  159. EmsSUsed    dw      0                       ; saved records used
  160. EmsSOld     dw      0                       ; saved oldest record
  161. EmsWrites   dw      0                       ; writes since save
  162.  
  163. EmsHndl     dw      0                       ; EMS handle
  164.  
  165. EmsFrame    dw      0                       ; segment of page frame
  166.  
  167. EmsTbl      label   byte                    ; function dispatch table
  168.             dw      Ems0                    ; Initialize
  169.             dw      Ems1                    ; Read Record
  170.             dw      Ems2                    ; Write Record
  171.             dw      Ems3                    ; Get number of records
  172.             dw      Ems4                    ; Free EMS memory
  173.             dw      Ems5                    ; Save 4k
  174.             dw      Ems6                    ; Restore 4k
  175.  
  176. ; ---------------------
  177. ; Interface Entry Point
  178. ; ---------------------
  179.  
  180. Ems         proc    Far                     ; dispatch the call
  181.             push    si                      ; save registers
  182.             push    ds
  183.             push    es
  184.  
  185.             cmp     ax, MaxFunction         ; q. out of range?
  186.             ja      EmsRtnErr               ; a. yes .. error
  187.  
  188.             shl     ax, 1                   ; ax = ax * 2 (table index)
  189.             mov     si, ax                  ; si = table index
  190.             jmp     word ptr cs:EmsTbl[si]  ; go to the routine
  191.  
  192.  
  193. ; --------------
  194. ; Error return..
  195. ; --------------
  196.  
  197. EmsRtnErr:  stc                             ; set the carry bit
  198.  
  199.             pop     es                      ; restore
  200.             pop     ds                      ; ..saved
  201.             pop     si                      ; .. ..registers
  202.  
  203.             ret                             ; return with error
  204.  
  205.  
  206. ; -----------
  207. ; Return OK..
  208. ; -----------
  209.  
  210. EmsRtnOk:   clc                             ; reset carry bit
  211.  
  212.             pop     es                      ; restore
  213.             pop     ds                      ; ..saved
  214.             pop     si                      ; .. ..registers
  215.  
  216.             ret                             ; return OK
  217.  
  218.  
  219. ; --------------------------------------------------
  220. ; Initialization; cx = number of records to allocate
  221. ; --------------------------------------------------
  222.  
  223. Ems0        label   byte
  224.  
  225.             push    bx                      ; save registers
  226.             push    dx
  227.             push    di
  228.             push    si
  229.  
  230.             mov     cs:EmsRecs, cx          ; save records requested
  231.  
  232.             xor     ax, ax                  ; clear ax
  233.             mov     ds, ax                  ; ds -> low memory
  234.  
  235.             mov     ax, Ems67v+2            ; ax =  int 67's segment
  236.             mov     ds, ax                  ; ds -> int 67's segment
  237.             mov     si, 0ah                 ; ds:si -> signature, if any
  238.  
  239.             push    cs                      ; save our segment
  240.             pop     es                      ; es -> our segment
  241.             lea     di, cs:EmsSig           ; si -> signature expected
  242.  
  243.             cld                             ; ensure incremental compare
  244.             mov     cx, 8                   ; bytes to test
  245.  
  246.        repe cmpsb                           ; q. EMS found?
  247.             jne     Ems0Err                 ; a. no .. error
  248.  
  249. ;
  250. ; Get the page frame segment
  251. ;
  252.  
  253.             mov     ah, 41h                 ; ah = get page frame address
  254.             int     67h                     ; get the page frame
  255.  
  256.             or      ah, ah                  ; q. any problem?
  257.             jne     Ems0Err                 ; a. yes .. error
  258.  
  259.             mov     cs:EmsFrame, bx         ; save the segment
  260.  
  261. ;
  262. ; EMS found .. Allocate the buffer (if possible)
  263. ;
  264.  
  265.             mov     bx, cs:EmsRecs          ; bx = number of records req'd
  266.  
  267.             add     bx, 15                  ; Round up ..
  268.             and     bx, 0fff0h              ; ..to next 16
  269.             mov     cs:EmsRecs, bx          ; save in records available
  270.  
  271.             mov     cl, 4                   ; cl = shift counter
  272.             shr     bx, cl                  ; bx = bx / 16
  273.  
  274.             mov     ah, 43h                 ; ah = allocate memory
  275.             int     67h                     ; ..ask EMS for the memory
  276.  
  277.             or      ah, ah                  ; q. memory found?
  278.             jne     Ems0Err                 ; a. no .. error
  279.  
  280.             mov     cs:EmsHndl, dx          ; save the handle
  281.  
  282. ;
  283. ; Return with no error ..
  284. ;
  285.  
  286.             pop     si                      ; restore registers
  287.             pop     di
  288.             pop     dx
  289.             pop     bx
  290.             jmp     EmsRtnOk                ; ..return no error
  291.  
  292. ;
  293. ; Return with an error ..
  294. ;
  295.  
  296. Ems0Err:    pop     si                      ; restore registers
  297.             pop     di
  298.             pop     dx
  299.             pop     bx
  300.             jmp     EmsRtnErr               ; ..return w/error
  301.  
  302.  
  303. ; ------------------------------------------------
  304. ; Read record; bx = record number; es:di -> buffer
  305. ; ------------------------------------------------
  306.  
  307. Ems1        label   byte
  308.  
  309.             cmp     bx, cs:EmsUsed          ; q. valid record number?
  310.             jae     EmsRtnErr               ; a. no .. exit now
  311.  
  312.             push    cx                      ; save registers
  313.             push    dx
  314.             push    di
  315.  
  316.             mov     ah, 47h                 ; ah = save page map
  317.             mov     dx, cs:EmsHndl          ; dx = our handle
  318.             int     67h                     ; save current map
  319.  
  320.             add     bx, cs:EmsOld           ; add in oldest record number
  321.  
  322.             cmp     bx, cs:EmsUsed          ; q. beyond end of buffer?
  323.             jb      Ems1$10                 ; a. no .. use this number
  324.  
  325.             sub     bx, cs:EmsUsed          ; bx = record number
  326.  
  327. Ems1$10:    mov     si, bx                  ; si = real record number
  328.             mov     cl, 4                   ; cl = shift counter
  329.             shr     bx, cl                  ; bx = bx / 16 (EMS page number)
  330.  
  331.             and     si, 0fh                 ; si = record in page
  332.             mov     cl, 10                  ; cl = shift counter
  333.             shl     si, cl                  ; si = si * 1024 (offset in page)
  334.  
  335.             mov     ax, 4400h               ; ax = map into frame page 0
  336.             int     67h                     ; ..get the page from EMS
  337.  
  338.             push    ax                      ; save return code
  339.  
  340.             mov     ds, cs:EmsFrame         ; ds:si-> record in EMS
  341.  
  342.             cld                             ; assure incremental move
  343.             mov     cx, RecSize/2           ; ..512 words (or 1024 bytes)
  344.       rep   movsw                           ; ..move the record
  345.  
  346.             mov     ah, 48h                 ; ah = restore page map
  347.             int     67h                     ; ..ask EMS to do it
  348.  
  349.             pop     ax                      ; restore return code
  350.  
  351.             or      ah, ah                  ; q. any error in map page?
  352.             jnz     Ems1Err                 ; a. yes .. return with error
  353.  
  354. ;
  355. ; Return with no error ..
  356. ;
  357.  
  358.             pop     di                      ; restore registers
  359.             pop     dx
  360.             pop     cx
  361.             jmp     EmsRtnOk                ; return without error
  362.  
  363.  
  364. ;
  365. ; Return with an error ..
  366. ;
  367.  
  368. Ems1Err:    pop     di                      ; restore registers
  369.             pop     dx
  370.             pop     cx
  371.             jmp     EmsRtnErr               ; return with error
  372.  
  373.  
  374. ; ------------------------------------
  375. ; Write record; ds:bx -> record buffer
  376. ; ------------------------------------
  377.  
  378. Ems2        label   byte
  379.  
  380.             push    bx                      ; save registers
  381.             push    cx
  382.             push    dx
  383.             push    di
  384.  
  385.             mov     si, bx                  ; ds:si -> record
  386.  
  387.             mov     bx, cs:EmsUsed          ; bx = records used
  388.  
  389.             cmp     bx, cs:EmsRecs          ; q. all records used?
  390.             jnb     Ems2$10                 ; a. yes .. use old to calc
  391.  
  392.             inc     cs:EmsUsed              ; Add to used records
  393.             jmp     short Ems2$20           ; ..continue
  394.  
  395. Ems2$10:    mov     bx, cs:EmsOld           ; bx = next record to write
  396.  
  397.             lea     ax, 1[bx]               ; ax = bx + 1 (next old record)
  398.  
  399.             cmp     ax, cs:EmsRecs          ; q. hit the top of buffer?
  400.             jb      Ems2$15                 ; a. no .. continue
  401.  
  402.             xor     ax, ax                  ; else .. ax = first rec in EMS
  403.  
  404. Ems2$15:    mov     cs:EmsOld, ax           ; EmsOld = oldest record number
  405.  
  406. ;
  407. ; When we get here, bx contains the record number
  408. ;
  409.  
  410. Ems2$20:    mov     di, bx                  ; di = record number
  411.             mov     cl, 4                   ; cl = shift counter
  412.             shr     bx, cl                  ; bx = bx / 16 (EMS page number)
  413.  
  414.             and     di, 0fh                 ; di = record in page
  415.             mov     cl, 10                  ; cl = shift counter
  416.             shl     di, cl                  ; di = di * 1024 (offset in page)
  417.  
  418.             mov     ah, 47h                 ; ah = save page map
  419.             mov     dx, cs:EmsHndl          ; dx = our handle
  420.             int     67h                     ; save current map
  421.  
  422.             mov     ax, 4400h               ; ax = map into frame page 0
  423.             int     67h                     ; ..get the page from EMS
  424.  
  425.             or      ah, ah                  ; q. any error in map page?
  426.             jnz     Ems2Err                 ; a. yes .. return with error
  427.  
  428.             mov     es, cs:EmsFrame         ; es:di -> record in EMS
  429.  
  430.             cld                             ; assure incremental move
  431.             mov     cx, RecSize/2           ; ..512 words (or 1024 bytes)
  432.       rep   movsw                           ; ..move the record
  433.  
  434. ;
  435. ; Return with no error ..
  436. ;
  437.  
  438.             mov     ah, 48h                 ; ah = restore page map
  439.             mov     dx, cs:EmsHndl          ; dx = our handle
  440.             int     67h                     ; ..ask EMS to do it
  441.  
  442.             inc     cs:EmsWrites            ; ..increment write counter
  443.  
  444.             pop     di                      ; restore registers
  445.             pop     dx
  446.             pop     cx
  447.             pop     bx
  448.             jmp     EmsRtnOk                ; return without error
  449.  
  450.  
  451. ;
  452. ; Return with an error ..
  453. ;
  454.  
  455. Ems2Err:    mov     ah, 48h                 ; ah = restore page map
  456.             mov     dx, cs:EmsHndl          ; dx = our handle
  457.             int     67h                     ; ..ask EMS to do it
  458.  
  459.             pop     di                      ; restore registers
  460.             pop     dx
  461.             pop     cx
  462.             pop     bx
  463.             jmp     EmsRtnErr               ; return with error
  464.  
  465. ; --------------------------
  466. ; Get number of used records
  467. ; --------------------------
  468.  
  469. Ems3        label   byte
  470.  
  471.             mov     ax, cs:EmsUsed          ; ax = records used
  472.             jmp     EmsRtnOk                ; ..return ok
  473.  
  474.  
  475. ; ---------------------
  476. ; Release scroll buffer
  477. ; ---------------------
  478.  
  479. Ems4        label   byte
  480.  
  481.             push    dx                      ; save registers
  482.  
  483.             mov     ah, 45h                 ; ah = deallocate EMS pages
  484.             mov     dx, cs:EmsHndl          ; dx = our EMS handle
  485.             int     67h                     ; ..Hey, EMS, deallocate it!
  486.  
  487.             pop     dx
  488.             jmp     EmsRtnOk                ; return no error
  489.  
  490. Ems         endp
  491.  
  492.  
  493. ; --------------------
  494. ; Save record pointers
  495. ; --------------------
  496.  
  497. Ems5        label   byte
  498.  
  499.             push    cs:EmsUsed              ; save records used
  500.             pop     cs:EmsSUsed             ; ..in save field
  501.  
  502.             push    cs:EmsOld               ; save oldest record
  503.             pop     cs:EmsSOld              ; ..in save field
  504.  
  505.             mov     cs:EmsWrites, 0         ; zero write counter
  506.  
  507.             jmp     EmsRtnOk                ; ..return without error
  508.  
  509. ; -----------------------
  510. ; Restore record pointers
  511. ; -----------------------
  512.  
  513. Ems6        label   byte
  514.  
  515.             push    cs:EmsSUsed             ; reload used field
  516.             pop     cs:EmsUsed              ; ..from save field
  517.  
  518.             push    cs:EmsSOld              ; reload oldest record
  519.             pop     cs:EmsOld               ; ..from save field
  520.  
  521.             mov     ax, cs:EmsWrites        ; return number of writes
  522.             jmp     EmsRtnOk                ; ..return without error
  523.  
  524.             align   16                      ; boundary for next driver
  525. EmsEnd      label   byte
  526.  
  527. EmsInt      ends
  528.  
  529.             
  530.             IFNDEF  Borland                 ; Assemble in MASM only
  531.  
  532. ENDSTMT     macro                           ; macro only needed with MASM
  533.             end     EmsStart                ; end the assembly
  534.             endm
  535.             
  536.             ENDIF
  537.  
  538.             ENDSTMT                         ; varies with Tasm and Asm
  539.