home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / memory / umb_man / umm.asm < prev    next >
Assembly Source File  |  1991-10-05  |  11KB  |  534 lines

  1. ;; umm.asm v0.2
  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
  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. ;;
  42.  
  43.     ideal                ; Use TASM Ideal mode syntax
  44.     p286n                ; Assemble for the 80286 (real mode)
  45.     locals    $$            ; local labels preceded by '$$'
  46.  
  47. mbds    equ    (mb ds:0)
  48. mbes    equ    (mb es:0)
  49. rhds    equ    (rh ds:si)
  50. rhes    equ    (rh es:di)
  51.  
  52. macro    pushfm
  53.     pushf
  54.     push    cs
  55. endm
  56.  
  57. macro    popfm
  58.     call    iretm
  59. endm
  60.  
  61. struc    rh                ; request header
  62. len    db    ?
  63. dev    db    ?
  64. cmd    db    ?
  65. st    dw    ?
  66. rsvd    dq    ?
  67. ct    db    ?
  68. aoff    dw    ?
  69. aseg    dw    ?
  70. dptr    dd    ?
  71. ends
  72.  
  73. struc    mb                ; UMB header
  74. nxt    dw    ?            ; next UMB in chain
  75. siz    dw    ?            ; size of UMB (without header)
  76. mlo    dw    ?            ; magic number (low word)
  77. mhi    dw    ?            ; magic humber (high word)
  78. extra    dq    ?            ; extra (unused)
  79. ends
  80.  
  81. segment    umm    use16
  82.  
  83. devhdr    dd    -1            ; device header
  84. devflg    dw    0a000h
  85. devstr    dw    ummstr
  86. devint    dw    ummint0
  87. devnam    db    'UMMXXXX0'
  88.  
  89. fpseg    dw    ?            ; paragraph address of freep
  90.  
  91. label    rhptr    dword            ; pointer to request header
  92. rhoff    dw    ?
  93. rhseg    dw    ?
  94.  
  95. label    xmmptr    dword            ; pointer to XMM
  96. xmmoff    dw    ?
  97. xmmseg    dw    ?
  98.  
  99. iretm:    iret                ; part of pushfm/popfm macro set
  100.  
  101.     align    16            ; force freep to be paragraph-aligned
  102.  
  103. freep    dw    -1            ; segment of first free UMB
  104.  
  105. proc    ummstr    far            ; strategy routine
  106.     assume    cs:umm
  107.  
  108.     mov    [rhoff], bx
  109.     mov    [rhseg], es
  110.     ret
  111. endp
  112.  
  113. proc    ummint    far            ; resident interrupt routine
  114.     assume    cs:umm
  115.  
  116.     push    si            ; save registers
  117.     push    ds
  118.     lds    si, [rhptr]        ; ds:si = request header
  119.     mov    [rhds.st], 8103h    ; return error (unknown command)
  120.     pop    ds            ; restore registers
  121.     pop    si
  122.     ret
  123. endp
  124.  
  125. label    hdrend    unknown            ; HEADER SECTION ENDS HERE
  126.  
  127. proc    ummctl    far            ; UMM control function
  128.     assume    cs:umm
  129.  
  130.     jmp    short $$1        ; XMS requires this
  131.     nop
  132.     nop
  133.     nop
  134.  
  135. $$1:    pushfm                ; save flags
  136.     cmp    ah, 10h            ; request UMB
  137.     je    short $$2
  138.     cmp    ah, 11h            ; release UMB
  139.     je    short $$3
  140.     popfm
  141.     jmp    [xmmptr]        ; chain to old XMM
  142.  
  143. $$2:    push    ds            ; save segment registers
  144.     push    es
  145.     call    requmb            ; request UMB
  146.     jmp    short $$4
  147.  
  148. $$3:    push    ds            ; save segment registers
  149.     push    es
  150.     call    relumb            ; release UMB
  151.  
  152. $$4:    pop    es            ; restore segment registers
  153.     pop    ds
  154.     popfm                ; restore flags before returning
  155.     ret
  156. endp
  157.  
  158. proc    requmb    near            ; request UMB
  159.     assume    cs:umm
  160.  
  161.     cmp    [freep], -1        ; any UMBs available?
  162.     jne    short $$1
  163.     xor    ax, ax            ; return failure code
  164.     mov    bl, 0b1h        ; no UMBs available
  165.     ret
  166.  
  167. $$1:    mov    ds, [fpseg]        ; get paragraph address of freep
  168.     push    cx
  169.     xor    cx, cx
  170.  
  171. $$2:    cmp    [mbds.nxt], -1        ; last UMB?
  172.     jne    short $$3
  173.     xor    ax, ax            ; return failure code
  174.     mov    bl, 0b0h        ; smaller UMB available
  175.     mov    dx, cx
  176.     pop    cx
  177.     ret
  178.  
  179. $$3:    mov    ax, ds            ; save previous UMB
  180.     mov    ds, [mbds.nxt]        ; move to next UMB
  181.     cmp    [mbds.siz], cx        ; remember size of largest UMB
  182.     jbe    short $$4
  183.     mov    cx, [mbds.siz]
  184.  
  185. $$4:    cmp    cx, dx            ; big enough?
  186.     jb    short $$2
  187.     sub    cx, dx            ; split into two UMBs if necessary
  188.     cmp    cx, 1
  189.     ja    short $$5
  190.     mov    es, ax            ; unlink current UMB
  191.     mov    ax, [mbds.nxt]
  192.     mov    [mbes.nxt], ax
  193.     jmp    short $$6
  194.  
  195. $$5:    mov    ax, ds            ; determine address of new UMB
  196.     add    ax, cx
  197.     dec    cx            ; shorten old UMB
  198.     mov    [mbds.siz], cx
  199.     mov    ds, ax            ; initialize new UMB
  200.     mov    [mbds.siz], dx
  201.     mov    [mbds.mlo], 4c4bh
  202.     mov    [mbds.mhi], 0047h
  203.  
  204. $$6:    mov    ax, 1            ; return success code
  205.     mov    bx, ds            ; return address of UMB
  206.     inc    bx
  207.     pop    cx
  208.     ret
  209. endp
  210.  
  211. proc    relumb    near            ; release UMB
  212.     assume    cs:umm
  213.  
  214.     push    dx
  215.     dec    dx
  216.     mov    es, dx
  217.     cmp    [mbes.mlo], 4c4bh    ; check magic number
  218.     jne    short $$1
  219.     cmp    [mbes.mhi], 0047h
  220.     je    short $$2
  221.  
  222. $$1:    xor    ax, ax            ; return failure code
  223.     mov    bl, 0b2h        ; invalid UMB
  224.     pop    dx
  225.     ret
  226.  
  227. $$2:    mov    ds, [fpseg]        ; get paragraph address of freep
  228.  
  229. $$3:    cmp    [mbds.nxt], dx        ; step through linked list
  230.     ja    short $$4
  231.     mov    ds, [mbds.nxt]
  232.     jmp    short $$3
  233.  
  234. $$4:    mov    ax, [mbds.nxt]        ; link UMB back into list
  235.     mov    [mbes.nxt], ax
  236.     mov    [mbds.nxt], dx
  237.     mov    ds, [fpseg]        ; 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    ummend    unknown            ; RESIDENT PORTION ENDS HERE
  265.  
  266.     align    4            ; start this section on dword boundary
  267.  
  268. newsp    dw    stktop            ; stack for initialization routine
  269. newss    dw    ?
  270. oldsp    dw    ?            ; original stack
  271. oldss    dw    ?
  272.  
  273. proc    ummint0    far            ; initial interrupt routine
  274.     assume    cs:umm
  275.  
  276.     pushfm                ; save flags
  277.     pusha                ; save registers
  278.     push    ds
  279.     push    es
  280.     push    cs
  281.     pop    ds
  282.     mov    [ds:newss], ds
  283.     les    di, [ds: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.     popfm                ; 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    ss, [newss]        ; enable new stack
  303.     mov    sp, [newsp]
  304.     mov    ah, 9            ; write banner
  305.     mov    dx, offset eHello
  306.     int    21h
  307.     mov    [devint], offset ummint    ; enable resident interrupt routine
  308.     mov    ax, offset freep    ; initialize fpseg
  309.     shr    ax, 4
  310.     add    ax, [newss]
  311.     mov    [fpseg], ax
  312.     mov    ax, 4300h        ; check for an XMS driver
  313.     int    2fh
  314.     cmp    al, 80h            ; is the XMS driver loaded?
  315.     je    short lexer
  316.     mov    dx, offset eNoXMS
  317.  
  318. abort:    call    error            ; abort installation
  319.     mov    [rhes.aseg], cs        ; discard everything after header
  320.     mov    [rhes.aoff], offset hdrend
  321.     mov    [rhes.st], 810ch    ; return error (general failure)
  322.     mov    ss, [oldss]        ; restore old stack
  323.     mov    sp, [oldsp]
  324.     ret
  325.  
  326. badch:    pop    ds            ; bad character found by lexer
  327.     mov    dx, offset eLexer
  328.     jmp    short abort
  329.  
  330. lexer:    push    ds            ; lexical analyzer
  331.     lds    si, [rhes.dptr]        ; ds:si = command line arguments
  332.     cld
  333.  
  334. s0:    lodsb                ; state 0, skip filename
  335.     call    eol
  336.     je    short done
  337.     call    blank
  338.     jne    short s0
  339.  
  340. s1:    lodsb                ; state 1, skip blanks
  341.     call    eol
  342.     je    short done
  343.     call    blank
  344.     je    short s1
  345.     call    digit
  346.     ja    short badch
  347.  
  348.     cbw
  349.     mov    cx, ax
  350. s2:    lodsb                ; state 2, found 1 decimal digit
  351.     cmp    al, '@'
  352.     je    short s4
  353.     call    digit
  354.     ja    short badch
  355.  
  356.     imul    cx, 10
  357.     add    cx, ax
  358. s3:    lodsb                ; state 3, found 2 decimal digits
  359.     cmp    al, '@'
  360.     jne    short badch
  361.  
  362. s4:    lodsb                ; state 4, get first hex digit (a-f)
  363.     call    hexaf
  364.     ja    short badch
  365.     add    al, 10
  366.     mov    bh, al
  367.  
  368. s5:    lodsb                ; state 5, get second hex digit (0-f)
  369.     mov    bl, al
  370.     call    digit
  371.     jbe    short $$1
  372.     mov    al, bl
  373.     call    hexaf
  374.     ja    short badch
  375.     add    al, 10
  376.  
  377. $$1:    shl    bh, 4
  378.     or    bh, al
  379.     xor    bl, bl
  380.  
  381. s6:    lodsb                ; state 6, get third hex digit (0)
  382.     cmp    al, '0'
  383.     jne    short badch
  384.  
  385. s7:    lodsb                ; state 7, get fourth hex digit (0)
  386.     cmp    al, '0'
  387.     jne    short badch
  388.     call    newumb            ; create new UMB
  389.     jmp    short s1
  390.  
  391. done:    pop    ds            ; command-line processing done
  392.     mov    [rhes.aseg], cs        ; discard initialization section
  393.     mov    [rhes.aoff], offset ummend
  394.     mov    [rhes.st], 0100h    ; return success code
  395.     mov    ax, 4310h        ; hook XMS control function
  396.     int    2fh
  397. $$2:    cmp    [byte es:bx], 0ebh    ; does it start with a short jump?
  398.     je    short $$3
  399.     les    bx, [es:bx+1]        ; if not, follow far jump
  400.     jmp    short $$2
  401. $$3:    mov    [byte es:bx], 0eah    ; change to a long jump
  402.     inc    bx            ; load byte displacement
  403.     mov    al, [byte es:bx]
  404.     cbw                ; convert to word offset
  405.     add    ax, bx
  406.     inc    ax
  407.     mov    [xmmoff], ax        ; link ourselves into the chain
  408.     mov    [xmmseg], es
  409.     mov    [word es:bx], offset ummctl
  410.     mov    [word es:bx+2], cs
  411.     mov    ss, [oldss]        ; restore old stack
  412.     mov    sp, [oldsp]
  413.     ret
  414. endp
  415.  
  416. proc    eol    near            ; check if al is an eol or eof
  417.     assume    cs:umm
  418.  
  419.     cmp    al, 13
  420.     je    short $$1
  421.     cmp    al, 26
  422. $$1:    ret
  423. endp
  424.  
  425. proc    blank    near            ; check if al is a space or tab
  426.     assume    cs:umm
  427.  
  428.     cmp    al, 32
  429.     je    short $$1
  430.     cmp    al, 9
  431. $$1:    ret
  432. endp
  433.  
  434. proc    digit    near            ; check if al is a decimal digit
  435.     assume    cs:umm
  436.  
  437.     sub    al, '0'
  438.     cmp    al, 9
  439.     ret
  440. endp
  441.  
  442. proc    hexaf    near            ; check if al is in the range 'a'-'f'
  443.     assume    cs:umm
  444.  
  445.     or    al, 32
  446.     sub    al, 'a'
  447.     cmp    al, 5
  448.     ret
  449. endp
  450.  
  451. proc    error    near            ; write an error message
  452.     assume    cs:umm, ds:umm
  453.  
  454.     mov    ah, 9
  455.     push    dx
  456.     mov    dx, offset eError    ; write error prefix
  457.     int    21h
  458.     pop    dx            ; specify which error
  459.     int    21h
  460.     ret
  461. endp
  462.  
  463. proc    newumb    near            ; create a new UMB
  464.     assume    cs:umm
  465.  
  466.     push    ds
  467.     push    es
  468.     mov    es, [cs:fpseg]        ; get paragraph address of freep
  469.  
  470. $$1:    cmp    [mbes.nxt], bx        ; step through linked list
  471.     ja    short $$2
  472.     mov    es, [mbes.nxt]
  473.     jmp    short $$1
  474.  
  475. $$2:    push    es            ; memory test
  476.     push    bx
  477.     push    cx
  478.     push    di
  479.     mov    dx, cx
  480.      mov    ax, 0a396h        ; test pattern
  481.  
  482. $$3:    mov    es, bx            ; write test pattern to page
  483.     mov    cx, 2048
  484.     xor    di, di
  485.     rep    stosw
  486.     mov    cx, 2048        ; read test pattern from page
  487.     xor    di, di
  488.     repe    scasw
  489.     jne    short $$4
  490.     inc    bh            ; move to next page
  491.     dec    dx
  492.     jnz    short $$3
  493.     jmp    short $$5
  494.  
  495. $$4:    add    sp, 14            ; error in memory test
  496.     pop    ds
  497.     les    di, [ds:rhptr]
  498.     mov    dx, offset eNoMem
  499.     jmp    abort
  500.  
  501. $$5:    pop    di            ; memory tested ok
  502.     pop    cx
  503.     pop    bx
  504.     pop    es
  505.     xchg    cl, ch            ; convert pages to paragraphs
  506.     dec    cx
  507.     mov    ds, bx
  508.     mov    ax, [mbes.nxt]        ; link UMB into list
  509.     mov    [mbds.nxt], ax
  510.     mov    [mbes.nxt], bx
  511.     mov    [mbds.siz], cx        ; initialize UMB
  512.     mov    [mbds.mlo], 4c4bh
  513.     mov    [mbds.mhi], 0047h
  514.     pop    es
  515.     pop    ds
  516.     ret
  517. endp
  518.  
  519. eHello    db    'Upper Memory Manager v0.2', 13, 10
  520.     db    'Copyright (C) 1991  Kenneth Gober'
  521. eNL    db    13, 10, 13, 10, '$'
  522. eError    db    'Error installing UMM:  $'
  523. eNoXMS    db    'XMS driver not found', 13, 10, '$'
  524. eLexer    db    'Invalid arguments', 13, 10, '$'
  525. eNoMem    db    'Memory test failed', 13, 10, '$'
  526.  
  527.     align    4            ; start stack on dword boundary
  528.  
  529. stkbot    db    512 dup (?)        ; initialization stack
  530. label    stktop    word
  531.  
  532. ends    umm
  533.     end
  534.