home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / SYSTEM / UMM03.ZIP / UMM.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-12-14  |  11.9 KB  |  563 lines

  1. ;; umm.asm v0.3
  2. ;; Upper Memory Manager for MS-DOS
  3. ;; Copyright (C) 1991  Kenneth Gober
  4. ;;
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation; either version 2 of the License, or
  8. ;; (at your option) any later version.
  9. ;;
  10. ;; This program is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;; GNU General Public License for more details.
  14. ;;
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with this program; if not, write to the Free Software
  17. ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ;;
  19. ;; To contact the author about changes, enhancements, bug reports, or
  20. ;; other comments, send electronic mail to:
  21. ;;
  22. ;;    snow@drycas (from Bitnet sites)
  23. ;;    snow@drycas.club.cc.cmu.edu (from Internet sites)
  24. ;;
  25. ;; If you are unable to contact the author through electronic mail,
  26. ;; try sending a letter (as a last resort, only) to the following address:
  27. ;;
  28. ;;    Kenneth Gober
  29. ;;    412 Robin Road
  30. ;;    Cedar Hill, TX 75104 (USA)
  31. ;;
  32. ;; Please note that mail sent to this address may not yield a response
  33. ;; for several months!
  34. ;;
  35. ;; Version History:
  36. ;;
  37. ;;    0.0    Initial release for 80386 only.
  38. ;;    0.1    Provided 80286 support.
  39. ;;    0.2    Memory test added.  Bug in UMB merge code fixed by
  40. ;;          ajr@cybill.inesc.pt (Antonio Julio Raposo).
  41. ;;    0.3    Resident portion relocated to upper memory.
  42. ;;
  43.  
  44.     ideal                ; Use TASM Ideal mode syntax
  45.     p286n                ; Assemble for the 80286 (real mode)
  46.     locals    $$            ; local labels preceded by '$$'
  47.  
  48. mbds    equ    (mb ds:0)
  49. mbes    equ    (mb es:0)
  50. rhds    equ    (rh ds:si)
  51. rhes    equ    (rh es:di)
  52.  
  53. struc    rh                ; request header
  54. len    db    ?
  55. dev    db    ?
  56. cmd    db    ?
  57. st    dw    ?
  58. rsvd    dq    ?
  59. ct    db    ?
  60. aoff    dw    ?
  61. aseg    dw    ?
  62. dptr    dd    ?
  63. ends
  64.  
  65. struc    mb                ; UMB header
  66. nxt    dw    ?            ; next UMB in chain
  67. siz    dw    ?            ; size of UMB (without header)
  68. mlo    dw    ?            ; magic number (low word)
  69. mhi    dw    ?            ; magic number (high word)
  70. extra    dq    ?            ; extra (unused)
  71. ends
  72.  
  73. group    umm    umml, ummh, umm0
  74.  
  75. segment    umml    use16            ; low-memory resident segment
  76.  
  77. devhdr    dd    -1            ; device header
  78. devflg    dw    0a000h
  79. devstr    dw    ummstr
  80. devint    dw    ummint0
  81. devnam    db    'UMMXXXX0'
  82.  
  83. label    rhptr    dword            ; pointer to request header
  84. rhoff    dw    ?
  85. rhseg    dw    ?
  86.  
  87. proc    ummstr    far            ; strategy routine
  88.     assume    cs:umml
  89.  
  90.     mov    [umml:rhoff], bx
  91.     mov    [umml:rhseg], es
  92.     ret
  93. endp
  94.  
  95. proc    ummint    far            ; resident interrupt routine
  96.     assume    cs:umml
  97.  
  98.     push    si            ; save registers
  99.     push    ds
  100.     lds    si, [umml:rhptr]    ; ds:si = request header
  101.     mov    [rhds.st], 8103h    ; return error (unknown command)
  102.     pop    ds            ; restore registers
  103.     pop    si
  104.     ret
  105. endp
  106.  
  107. label    endl    unknown            ; HEADER SECTION ENDS HERE
  108.  
  109. ends    umml
  110.  
  111. segment    ummh    use16            ; upper-memory resident segment
  112.  
  113. label    begh    unknown
  114.  
  115. freep    dw    -1            ; segment of first free UMB
  116.  
  117. label    xmmptr    dword            ; pointer to XMM
  118. xmmoff    dw    ?
  119. xmmseg    dw    ?
  120.  
  121. rpopf:    iret                ; for reliable popf
  122.  
  123. proc    ummctl    far            ; UMM control function
  124.     assume    cs:ummh
  125.  
  126.     jmp    short $$1        ; XMS requires this
  127.     nop
  128.     nop
  129.     nop
  130.  
  131. $$1:    pushf                ; save flags
  132.     push    cs
  133.     cmp    ah, 10h            ; request UMB
  134.     je    short $$2
  135.     cmp    ah, 11h            ; release UMB
  136.     je    short $$3
  137.     call    ummh:rpopf        ; restore flags
  138.     jmp    [ummh:xmmptr]        ; chain to old XMM
  139.  
  140. $$2:    push    ds            ; save segment registers
  141.     push    es
  142.     call    ummh:requmb        ; request UMB
  143.     jmp    short $$4
  144.  
  145. $$3:    push    ds            ; save segment registers
  146.     push    es
  147.     call    ummh:relumb        ; release UMB
  148.  
  149. $$4:    pop    es            ; restore segment registers
  150.     pop    ds
  151.     call    ummh:rpopf        ; restore flags before returning
  152.     ret
  153. endp
  154.  
  155. proc    requmb    near            ; request UMB
  156.     assume    cs:ummh
  157.  
  158.     cmp    [ummh:freep], -1    ; any UMBs available?
  159.     jne    short $$1
  160.     xor    ax, ax            ; return failure code
  161.     mov    bl, 0b1h        ; no UMBs available
  162.     ret
  163.  
  164. $$1:    push    cs            ; get paragraph address of freep
  165.     pop    ds
  166.     push    cx
  167.     xor    cx, cx
  168.  
  169. $$2:    cmp    [mbds.nxt], -1        ; last UMB?
  170.     jne    short $$3
  171.     xor    ax, ax            ; return failure code
  172.     mov    bl, 0b0h        ; smaller UMB available
  173.     mov    dx, cx
  174.     pop    cx
  175.     ret
  176.  
  177. $$3:    mov    ax, ds            ; save previous UMB
  178.     mov    ds, [mbds.nxt]        ; move to next UMB
  179.     cmp    [mbds.siz], cx        ; remember size of largest UMB
  180.     jbe    short $$4
  181.     mov    cx, [mbds.siz]
  182.  
  183. $$4:    cmp    cx, dx            ; big enough?
  184.     jb    short $$2
  185.     sub    cx, dx            ; split into two UMBs if necessary
  186.     cmp    cx, 1
  187.     ja    short $$5
  188.     mov    es, ax            ; unlink current UMB
  189.     mov    ax, [mbds.nxt]
  190.     mov    [mbes.nxt], ax
  191.     jmp    short $$6
  192.  
  193. $$5:    mov    ax, ds            ; determine address of new UMB
  194.     add    ax, cx
  195.     dec    cx            ; shorten old UMB
  196.     mov    [mbds.siz], cx
  197.     mov    ds, ax            ; initialize new UMB
  198.     mov    [mbds.siz], dx
  199.     mov    [mbds.mlo], 4c4bh
  200.     mov    [mbds.mhi], 0047h
  201.  
  202. $$6:    mov    ax, 1            ; return success code
  203.     mov    bx, ds            ; return address of UMB
  204.     inc    bx
  205.     pop    cx
  206.     ret
  207. endp
  208.  
  209. proc    relumb    near            ; release UMB
  210.     assume    cs:ummh
  211.  
  212.     push    dx
  213.     dec    dx
  214.     mov    es, dx
  215.     cmp    [mbes.mlo], 4c4bh    ; check magic number
  216.     jne    short $$1
  217.     cmp    [mbes.mhi], 0047h
  218.     je    short $$2
  219.  
  220. $$1:    xor    ax, ax            ; return failure code
  221.     mov    bl, 0b2h        ; invalid UMB
  222.     pop    dx
  223.     ret
  224.  
  225. $$2:    push    cs            ; get paragraph address of freep
  226.     pop    ds
  227.  
  228. $$3:    cmp    [mbds.nxt], dx        ; step through linked list
  229.     ja    short $$4
  230.     mov    ds, [mbds.nxt]
  231.     jmp    short $$3
  232.  
  233. $$4:    mov    ax, [mbds.nxt]        ; link UMB back into list
  234.     mov    [mbes.nxt], ax
  235.     mov    [mbds.nxt], dx
  236.     push    cs
  237.     pop    ds            ; try to merge adjacent UMBs
  238.     mov    ds, [mbds.nxt]
  239.  
  240. $$5:    cmp    [mbds.nxt], -1        ; end of chain?
  241.     jne    short $$6
  242.     mov    ax, 1            ; return success code
  243.     pop    dx
  244.     ret
  245.  
  246. $$6:    mov    ax, ds            ; advance to next UMB
  247.     mov    ds, [mbds.nxt]
  248.     mov    es, ax            ; see if UMBs are adjacent
  249.     add    ax, [mbes.siz]
  250.     inc    ax
  251.     mov    dx, ds
  252.     cmp    ax, dx
  253.     jne    short $$5
  254.     mov    ax, [mbds.nxt]        ; unlink second UMB
  255.     mov    [mbes.nxt], ax
  256.     mov    ax, [mbds.siz]        ; merge UMBs
  257.     inc    ax
  258.     add    [mbes.siz], ax
  259.     push    es            ; try merging this UMB again
  260.     pop    ds
  261.     jmp    short $$5
  262. endp
  263.  
  264. label    endh    unknown            ; RESIDENT SECTION ENDS HERE
  265.  
  266. ends    ummh
  267.  
  268. segment    umm0    use16            ; initialization segment
  269.  
  270. oldsp    dw    ?            ; original stack
  271. oldss    dw    ?
  272.  
  273. proc    ummint0    far            ; initial interrupt routine
  274.     assume    cs:umm, ds:umm
  275.  
  276.     pushf                ; save flags
  277.     push    cs
  278.     pusha                ; save registers
  279.     push    ds
  280.     push    es
  281.     push    cs
  282.     pop    ds
  283.     les    di, [rhptr]        ; es:di = request header
  284.     mov    [rhes.st], 8103h    ; assume error (unknown command)
  285.     mov    al, [rhes.cmd]        ; only cmd 0, INIT is legal
  286.     or    al, al
  287.     jnz    short $$1
  288.     call    init
  289.  
  290. $$1:    pop    es            ; restore registers
  291.     pop    ds
  292.     popa
  293.     call    rpopf            ; restore flags before returning
  294.     ret
  295. endp
  296.  
  297. proc    init    near            ; initialize driver
  298.     assume    cs:umm, ds:umm
  299.  
  300.     mov    [oldss], ss        ; save old stack
  301.     mov    [oldsp], sp
  302.     mov    bx, ds
  303.     mov    ss, bx            ; enable new stack
  304.     mov    sp, offset stktop
  305.     mov    ah, 9            ; write banner
  306.     mov    dx, offset eHello
  307.     int    21h
  308.     mov    [devint], offset ummint    ; enable resident interrupt routine
  309.     mov    ax, 4300h        ; check for an XMS driver
  310.     int    2fh
  311.     cmp    al, 80h            ; is the XMS driver loaded?
  312.     je    short lexer
  313.     mov    dx, offset eNoXMS
  314.  
  315. abort:    call    error            ; abort installation
  316.     mov    [rhes.aseg], cs        ; discard everything after header
  317.     mov    [rhes.aoff], offset endl
  318.     mov    [rhes.st], 810ch    ; return error (general failure)
  319.     mov    ss, [oldss]        ; restore old stack
  320.     mov    sp, [oldsp]
  321.     ret
  322.  
  323. badch:    pop    ds            ; bad character found by lexer
  324.     mov    dx, offset eLexer
  325.     jmp    short abort
  326.  
  327. lexer:    push    ds            ; lexical analyzer
  328.     lds    si, [rhes.dptr]        ; ds:si = command line arguments
  329.     cld
  330.  
  331. s0:    lodsb                ; state 0, skip filename
  332.     call    eol
  333.     je    short done
  334.     call    blank
  335.     jne    short s0
  336.  
  337. s1:    lodsb                ; state 1, skip blanks
  338.     call    eol
  339.     je    short done
  340.     call    blank
  341.     je    short s1
  342.     call    digit
  343.     ja    short badch
  344.  
  345.     cbw
  346.     mov    cx, ax
  347. s2:    lodsb                ; state 2, found 1 decimal digit
  348.     cmp    al, '@'
  349.     je    short s4
  350.     call    digit
  351.     ja    short badch
  352.  
  353.     imul    cx, 10
  354.     add    cx, ax
  355. s3:    lodsb                ; state 3, found 2 decimal digits
  356.     cmp    al, '@'
  357.     jne    short badch
  358.  
  359. s4:    lodsb                ; state 4, get first hex digit (a-f)
  360.     call    hexaf
  361.     ja    short badch
  362.     add    al, 10
  363.     mov    bh, al
  364.  
  365. s5:    lodsb                ; state 5, get second hex digit (0-f)
  366.     mov    bl, al
  367.     call    digit
  368.     jbe    short $$1
  369.     mov    al, bl
  370.     call    hexaf
  371.     ja    short badch
  372.     add    al, 10
  373.  
  374. $$1:    shl    bh, 4
  375.     or    bh, al
  376.     xor    bl, bl
  377.  
  378. s6:    lodsb                ; state 6, get third hex digit (0)
  379.     cmp    al, '0'
  380.     jne    short badch
  381.  
  382. s7:    lodsb                ; state 7, get fourth hex digit (0)
  383.     cmp    al, '0'
  384.     jne    short badch
  385.     call    newumb            ; create new UMB
  386.     jmp    short s1
  387.  
  388. done:    pop    ds            ; command-line processing done
  389.     mov    [rhes.aseg], cs        ; discard initialization section
  390.     mov    [rhes.aoff], offset endh
  391.     mov    [rhes.st], 0100h    ; return success code
  392.     mov    cx, offset ummh:endh    ; relocate resident portion
  393.     mov    dx, cx            ; find size in paragraphs
  394.     add    dx, 15
  395.     shr    dx, 4
  396.     mov    bx, cs            ; call UMM control function
  397.     mov    ax, offset begh        ; find segment
  398.     shr    ax, 4
  399.     add    bx, ax
  400.     mov    ah, 10h
  401.     push    bx            ; save ummh segment value
  402.     push    cs            ; push return address
  403.     push    offset $$ret
  404.     push    bx            ; push call address
  405.     push    offset ummh:ummctl
  406.     retf                ; this is a far call
  407. $$ret:    test    ax, ax            ; UMB available?
  408.     jz    hook
  409.     pop    ax            ; replace saved ummh segment value
  410.     push    bx            ; and relocate ummh to UMB
  411.     mov    [rhes.aoff], offset endl
  412.     mov    es, bx
  413.     mov    si, offset begh
  414.     xor    di, di
  415.     cld
  416.     rep    movsb
  417.  
  418. hook:    mov    ax, 4310h        ; hook XMS control function
  419.     int    2fh
  420. $$2:    cmp    [byte es:bx], 0ebh    ; does it start with a short jump?
  421.     je    short $$3
  422.     les    bx, [es:bx+1]        ; if not, follow far jump
  423.     jmp    short $$2
  424. $$3:    mov    [byte es:bx], 0eah    ; change to a long jump
  425.     inc    bx            ; load byte displacement
  426.     mov    al, [byte es:bx]
  427.     cbw                ; convert to word offset
  428.     add    ax, bx
  429.     inc    ax
  430.     pop    ds            ; restore saved ummh segment value
  431.     assume    cs:umm, ds:ummh
  432.     mov    [ummh:xmmoff], ax    ; link ourselves into the chain
  433.     mov    [ummh:xmmseg], es
  434.     mov    [word es:bx], offset ummh:ummctl
  435.     mov    [word es:bx+2], ds
  436.     mov    ss, [oldss]        ; restore old stack
  437.     mov    sp, [oldsp]
  438.     ret
  439. endp
  440.  
  441. proc    eol    near            ; check if al is an eol or eof
  442.     assume    cs:umm
  443.  
  444.     cmp    al, 13
  445.     je    short $$1
  446.     cmp    al, 26
  447. $$1:    ret
  448. endp
  449.  
  450. proc    blank    near            ; check if al is a space or tab
  451.     assume    cs:umm
  452.  
  453.     cmp    al, 32
  454.     je    short $$1
  455.     cmp    al, 9
  456. $$1:    ret
  457. endp
  458.  
  459. proc    digit    near            ; check if al is a decimal digit
  460.     assume    cs:umm
  461.  
  462.     sub    al, '0'
  463.     cmp    al, 9
  464.     ret
  465. endp
  466.  
  467. proc    hexaf    near            ; check if al is in the range 'a'-'f'
  468.     assume    cs:umm
  469.  
  470.     or    al, 32
  471.     sub    al, 'a'
  472.     cmp    al, 5
  473.     ret
  474. endp
  475.  
  476. proc    error    near            ; write an error message
  477.     assume    cs:umm, ds:umm
  478.  
  479.     mov    ah, 9
  480.     push    dx
  481.     mov    dx, offset eError    ; write error prefix
  482.     int    21h
  483.     pop    dx            ; specify which error
  484.     int    21h
  485.     ret
  486. endp
  487.  
  488. proc    newumb    near            ; create a new UMB
  489.     assume    cs:umm
  490.  
  491.     push    ds
  492.     push    es
  493.     mov    dx, cs            ; get paragraph address of freep
  494.     mov    ax, offset freep
  495.     shr    ax, 4
  496.     add    dx, ax
  497.     mov    es, dx
  498.  
  499. $$1:    cmp    [mbes.nxt], bx        ; step through linked list
  500.     ja    short $$2
  501.     mov    es, [mbes.nxt]
  502.     jmp    short $$1
  503.  
  504. $$2:    push    es            ; memory test
  505.     push    bx
  506.     push    cx
  507.     push    di
  508.     mov    dx, cx
  509.      mov    ax, 0a396h        ; test pattern
  510.  
  511. $$3:    mov    es, bx            ; write test pattern to page
  512.     mov    cx, 2048
  513.     xor    di, di
  514.     rep    stosw
  515.     mov    cx, 2048        ; read test pattern from page
  516.     xor    di, di
  517.     repe    scasw
  518.     jne    short $$4
  519.     inc    bh            ; move to next page
  520.     dec    dx
  521.     jnz    short $$3
  522.     jmp    short $$5
  523.  
  524. $$4:    add    sp, 14            ; error in memory test
  525.     pop    ds
  526.     les    di, [ds:rhptr]
  527.     mov    dx, offset eNoMem
  528.     jmp    abort
  529.  
  530. $$5:    pop    di            ; memory tested ok
  531.     pop    cx
  532.     pop    bx
  533.     pop    es
  534.     xchg    cl, ch            ; convert pages to paragraphs
  535.     dec    cx
  536.     mov    ds, bx
  537.     mov    ax, [mbes.nxt]        ; link UMB into list
  538.     mov    [mbds.nxt], ax
  539.     mov    [mbes.nxt], bx
  540.     mov    [mbds.siz], cx        ; initialize UMB
  541.     mov    [mbds.mlo], 4c4bh
  542.     mov    [mbds.mhi], 0047h
  543.     pop    es
  544.     pop    ds
  545.     ret
  546. endp
  547.  
  548. eHello    db    'Upper Memory Manager v0.3', 13, 10
  549.     db    'Copyright (C) 1991  Kenneth Gober'
  550. eNL    db    13, 10, 13, 10, '$'
  551. eError    db    'Error installing UMM:  $'
  552. eNoXMS    db    'XMS driver not found', 13, 10, '$'
  553. eLexer    db    'Invalid arguments', 13, 10, '$'
  554. eNoMem    db    'Memory test failed', 13, 10, '$'
  555.  
  556.     align    4            ; start stack on dword boundary
  557.  
  558. stkbot    db    512 dup (?)        ; initialization stack
  559. label    stktop    word
  560.  
  561. ends    umm0
  562.     end
  563.