home *** CD-ROM | disk | FTP | other *** search
/ DOS Wares / doswares.zip / doswares / UTILS / TOOLS / PERUSE.ZIP / PERASM.ZIP / PERUSEX.ASM < prev   
Encoding:
Assembly Source File  |  1994-02-09  |  17.3 KB  |  521 lines

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