home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / MEMORIA / EMMTEST.ZIP / NJRAMT.ASM next >
Encoding:
Assembly Source File  |  1987-10-21  |  14.5 KB  |  627 lines

  1.  
  2. ;    Nifty James' Famous Expanded Memory Tester
  3. ;    (C) Copyright 1987 by Mike Blaszczak.  All Rights Reserved.
  4.  
  5. ;   Version 1.00 of 21 Oct 1987
  6.  
  7. ;   Shareware  $5    Please register!
  8.  
  9. ;   Assemble with:
  10. ;    MASM NJRAMT;
  11. ;    LINK NJRAMD;
  12. ;    EXE2BIN NJRAMT.EXE NJRAMT.SYS
  13. ;    DEL NJRAMT.EXE
  14.  
  15. ;   for enhanced processor version:
  16.  
  17. ;    MASM /DV286 NJRAMT,NJRAMTXP;
  18. ;    LINK NJRAMTXP;
  19. ;    EXE2BIN NJRAMTXP.EXE NJRAMTXP.SYS
  20. ;    DEL NJRAMTXP.EXE
  21.  
  22. ;  --> DEVICE DRIVER FORMAT FILE <--
  23. ;  -->  REMEMBER TO USE EXE2BIN  <--
  24.  
  25. ; ---------------------------------------------------------------------------
  26.  
  27. ;   ASCII Characters
  28.  
  29. bell        equ    7        ; bell character
  30. tab        equ    9        ; tab character
  31. lf        equ    10        ; linefeed
  32. cr        equ    13        ; carriage return
  33. space        equ    32        ; space
  34. eos        equ    '$'        ; end of DOS string
  35.  
  36. ; ---------------------------------------------------------------------------
  37.  
  38. EMM        equ    067h        ; the E/EMS memory manager
  39.  
  40. ; ---------------------------------------------------------------------------
  41. ;  Structure Definitions
  42.  
  43. ;  The structures defined here are used to find information in the
  44. ;  various request header formats.  Of course, being structures, they
  45. ;  don't take up space... they are used to define offsets for the
  46. ;  addressing of the request header.
  47.  
  48. donestat    equ    00000000100000000b    ; done status bit flag
  49.  
  50. rq    equ    es:[bx]            ; base address used in routines
  51.  
  52. ;  -- Request Header (General Format)
  53.  
  54. inithead    struc
  55.     rlen    db    ?    ; length of the structure
  56.     unitn    db    ?    ; unit number
  57.     command    db    ?    ; command code
  58.     status    dw    ?    ; status code (returned by us)
  59.         db    8 dup(?); reserved bytes
  60.     units    db    ?    ; number of units
  61.     ndadro    dw    ?    ; ending address offset
  62.     ndadrs    dw    ?    ; ending address segment
  63.     bpboff    dw    ?    ; BPB offset pointer
  64.     bpbseg    dw    ?    ; BPB segment pointer
  65.     taglet    db    ?    ; drive tag letter
  66. inithead    ends
  67.  
  68. ; ---------------------------------------------------------------------------
  69. ;   DOS Calls
  70.  
  71. ; These are DOS functions used by the driver.
  72.  
  73. DisplayOut    equ    002h        ; call to print a single character
  74. PrintString    equ    009h        ; call to print a '$' string
  75. CheckKeyboard    equ    00Bh        ; call to check for a key
  76. GetDOSVersion    equ    030h        ; call to get the DOS version #
  77.  
  78. ; ---------------------------------------------------------------------------
  79. ;  I/O Ports
  80.  
  81. Speak        equ    061h        ; speaker port
  82. SpeakMask    equ    011111110b    ; mask for speaker set bit
  83. SpeakToggle    equ    000000010b    ; toggle bit for the speaker
  84.  
  85. ; ---------------------------------------------------------------------------
  86. ;  E/EMM Routines
  87.  
  88. ; These are the E/EMM functions that we use.  (These are specific functions
  89. ; of the EMM interrupt.)
  90.  
  91. E_PageBase    equ    041h        ; determine the Page Fram Base Addr
  92. E_Counts    equ    042h        ; determine free/total mem
  93. E_Open        equ    043h        ; open, allocate, obtain handle ID
  94. E_MapPage    equ    044h        ; map a logical page into window
  95. E_Close        equ    045h        ; close handle and free pages
  96. E_Version    equ    046h        ; get the E/EMM version number
  97.  
  98. ifdef  V286
  99.     .286
  100.     if1
  101.         %OUT    Enhanced processor version
  102.     endif
  103.     ifdef    PCL
  104.     if1
  105.         %OUT    for the PC's Limited 286/386
  106.     endif
  107.     endif
  108. else
  109.     if1
  110.         %OUT    Standard Version
  111.     endif
  112. endif
  113.  
  114.  
  115. ;  This macro is used during debugging.  It prints a single character
  116. ; via the BIOS screen interface, and leaves the registers unchanged.
  117.  
  118. ifdef    DEBUG
  119.  
  120.     if1
  121.         %OUT  DEBUG Version
  122.     endif
  123.     PrintChar    macro    Char
  124.         ifdef    PCL
  125.  
  126.             push    ax
  127.             mov    al,Char
  128.             out    095h,al        ; put it digit 3 of smartvu
  129.             pop    ax
  130.  
  131.         else
  132.     
  133.             push    ax        ; save the regs
  134.             push    bx
  135.             push    dx
  136.             mov    ah,15
  137.             int    010h        ; get the current page
  138.             mov    al,Char
  139.             mov    ah,14        ; print the character
  140.             int    010h
  141.  
  142.             xor    dx,dx
  143.             mov    ah,0        ; also to printer
  144.             mov    al,Char
  145.             int    017h
  146.  
  147.             pop    dx
  148.             pop    bx        ;restore the regs
  149.             pop    ax
  150.  
  151.             endif
  152.             endm
  153.  
  154. else
  155.     PrintChar    macro    Char        ; if not debugging, blow it off
  156.             endm
  157. endif
  158.  
  159. ; ---------------------------------------------------------------------------
  160.  
  161. tester        segment    para public 
  162.         assume    cs:tester,ds:tester,es:tester,ss:tester
  163.  
  164.         org    0        ; begin at zero
  165.  
  166. ; ---------------------------------------------------------------------------
  167. ;  Device Header
  168.  
  169. ; This area contains the header information.  It is used by DOS when loading
  170. ; the device driver, and it contains information used to describe the
  171. ; driver to the DOS environment.
  172.  
  173. NextPlace    dw    -1,-1        ; pointer to next driver
  174. Attrib        dw    00010000000000000b        ; attribute word
  175.             ;FEDCBA9876543210
  176.  
  177.                     ; device is non-ibm and block mode
  178.                     ; doesn't support IOCTL, is not
  179.                     ; a network device
  180.  
  181.         dw    offset Strategy        ; the strategy entry
  182.         dw    offset Interrupt    ; the interrupt entry
  183.         db    1,'NJ_DISK'        ;  Nifty James' Disk!
  184.  
  185. ; ---------------------------------------------------------------------------
  186.  
  187. JumpTable    label word
  188.  
  189. ; This area is a "Jump Table" that is used to dispatch the code.
  190. ; Only the init function is implemented.  This driver will only
  191. ; run during the CONFIG.SYS file.  After that, it entirely clears
  192. ; itself from memory.
  193.  
  194.     dw    offset    Init        ;  0 * initialize
  195.  
  196.     ;  (The commands above init are all not implemented -- we don't
  197.     ;   make entries for them to optimize for space (and speed).
  198.     ;   The equate TopCommand must be set to the last used
  199.     ;   command code.)
  200.  
  201. TopCommand    equ    1        ; highest valid command
  202.  
  203. RBPoint        label    dword        ; Pointer to request buffer
  204. RBPointOff    dw    0        ; offset part
  205. RBPointSeg    dw    0        ; segment part
  206.  
  207. SaveSS        dw    0        ; save place for the SS register
  208. SaveSP        dw    0        ; save place for the SP register
  209. SaveAX        dw    0        ; save place for the accumulator
  210.  
  211. EMMHandle    dw    0        ; our handle, as assigned by the EMM
  212. EMMBase        dw    0        ; base of the EMM physical window
  213.  
  214. ; ---------------------------------------------------------------------------
  215. ;  The local stack
  216.  
  217.         even            ; make the stack a word-aligned area
  218.         dw    64 dup (0DEADh)
  219. StackTop:
  220.  
  221. ; ---------------------------------------------------------------------------
  222. ;  Strategy Entry Point For the Device Driver
  223.  
  224. ;  This routine simply stores the pointer to the request header
  225. ;  so that request header has it.  That's all it does.  Really.
  226.  
  227. STRATPROC    proc    far
  228.  
  229. Strategy:
  230.     mov    cs:RBPointOff,bx
  231.     mov    cs:RBPointSeg,es    ; just store the pointer
  232.     ret                ; and get outta here!
  233.     ; (isn't it ironic that the shortest routine is called "Strategy"?)
  234. STRATPROC    endp
  235.  
  236. ; ---------------------------------------------------------------------------
  237. ;  Interrupt Entry Point For the Device Driver
  238.  
  239. ;  This routine executes the command contained in the passed request header.
  240. ;  DOS has called STRATEGY, and that routine stored a pointer to the request
  241. ;  header for our use.  We will construct our own stack area because the 
  242. ;  EMM uses a great deal of stack space.
  243.  
  244. INTPROC        proc    far
  245. Interrupt:    
  246. PrintChar 'D'
  247.         mov    CS:SaveSS,ss        ; save the SS register
  248.         mov    CS:SaveSP,sp        ; save the SP register
  249.         mov    CS:SaveAX,ax
  250.  
  251.         cli
  252.         mov    ax,offset StackTop    ; initialize our stack
  253.         mov    sp,ax
  254.         mov    ax,cs
  255.         mov    ss,ax
  256.         sti
  257.  
  258.     ifdef V286
  259.         pusha
  260.     else
  261.         push    bx        ; save the other regs
  262.         push    cx
  263.         push    dx
  264.         push    bp
  265.         push    si
  266.         push    di
  267.     endif
  268.  
  269.         pushf            ; and the flags
  270.         cld            ;  set the string direction up
  271.         push    es
  272.         push    ds
  273.  
  274.     ; Note that during calls we use DS to point to our local data
  275.     ; and ES to point to the request header.
  276.  
  277.         les    bx,cs:RBPoint    ; get the request buffer
  278.  
  279.         call    Init
  280.  
  281. ; ---------------------------------------------------------------------------
  282. ;   This is the mass exit; everone splits through this point!  When we
  283. ;   arrive here, the AX reg will contain the word to be put into the
  284. ;   status word.  We'll do that:
  285.  
  286. BigLog:        
  287. PrintChar 'X'
  288.         les    bx,cs:RBPoint        ; point to the request block
  289. NoRestore:    or    ax,donestat        ; set the done status
  290.         mov    rq.status,ax
  291.  
  292. ;  Now, we just undo the registers.
  293.  
  294.         pop    ds        ; the seg regs
  295.         pop    es
  296.  
  297.         popf            ; the flags
  298.     ifdef V286
  299.         popa
  300.     else
  301.         pop    di
  302.         pop    si        ; and the data regs
  303.         pop    bp
  304.         pop    dx
  305.         pop    cx
  306.         pop    bx
  307.     endif
  308.  
  309. PrintChar 'd'
  310.         cli
  311.         mov    ax,CS:SaveAX
  312.         mov    sp,CS:SaveSP    ; restore the calling stack
  313.         mov    ss,CS:SaveSS
  314.         sti
  315.         ret
  316.  
  317. INTPROC        endp
  318.  
  319. ; ---------------------------------------------------------------------------
  320.  
  321. testpage     proc    near
  322.  
  323.     ; This procedure tests the EMS block that is currently mapped
  324.     ; at EMSBASE:0000 through EMSBASE:3FFF.  The routine will return
  325.     ; with AX set to 0000h if no error occurred.  If an error occurs,
  326.     ; it returns with AX set to 0FFFFh.
  327.  
  328.         mov    es,EMSBase
  329.  
  330.         mov    ax,0FFFFh    ; write all ones
  331.         call    testset
  332.         jne    testfail    ; nope, it failed
  333.  
  334.         xor    ax,ax        ; write all zeros
  335.         call    testset
  336.         jne    testfail
  337.  
  338.         mov    ax,0AA55h    ; write 1010101001010101 pattern
  339.         call    testset
  340.         jne    testfail
  341.  
  342.         mov    ax,055AAh    ; write 0101010110101010 pattern
  343.         call    testset
  344.         jne    testfail
  345.  
  346.         xor    ax,ax        ; test was successful,
  347.         ret            ; return with AX = 0
  348.  
  349. testfail:    mov    ax,0FFFFh    ; AX = 0FFFFh, test failed.
  350.         ret
  351.  
  352. testpage    endp
  353.  
  354.  
  355. testset        proc    near
  356.  
  357.         cld
  358.         mov    di,0
  359.         mov    cx,8192        ; 8192 words
  360.     rep    stosw
  361.  
  362.         mov    di,0        ; try to check them
  363.         mov    cx,8190
  364. testsetloop:    cmp    es:[di],ax
  365.         jne    testsetexit
  366.         inc    di
  367.         inc    di
  368.         loop    testsetloop
  369.  
  370. testsetexit:    cmp    cx,0        ; see if it's zero
  371.         ret            ; and return with results of comparison
  372.  
  373. testset        endp
  374.  
  375. ; ---------------------------------------------------------------------------
  376.  
  377. PrintPage    proc    near
  378.  
  379.         xor    ax,ax            ; print "page x tested"
  380.         mov    si,offset TestingSpot
  381.         mov    bx,CurrentPage
  382.         call    Bin2Dec            ; convert page # to ASCII
  383.  
  384.         mov    ah,PrintString        ; print it
  385.         mov    dx,offset TestingMsg
  386.         int    21h
  387.  
  388.         in    al,Speak        ; and then make a click
  389.         and    al,SpeakMask
  390.         xor    al,SpeakToggle
  391.         out    Speak,al
  392.  
  393.         ret
  394.  
  395. PrintPage    endp
  396.  
  397. ; ---------------------------------------------------------------------------
  398.  
  399. PrintError    proc    near
  400.  
  401.         xor    ax,ax            ; print "error at page"
  402.         mov    si,offset ErrorSpot    ;  message
  403.         mov    bx,CurrentPage
  404.         call    Bin2Dec            ; convert page number to ASCII
  405.  
  406.         mov    ah,PrintString        ; and print it
  407.         mov    dx,offset ErrorMsg
  408.         int    21h
  409.  
  410.         ret
  411.  
  412.  
  413. PrintError    endp
  414.  
  415. ; ---------------------------------------------------------------------------
  416.  
  417. Init        proc    near
  418.  
  419.         mov    ax,cs
  420.         mov    ds,ax
  421.  
  422.         mov    ah,PrintString        ;print the banner
  423.         mov    dx,offset Banner
  424.         int    21h
  425.  
  426.         push    es
  427.         xor    ax,ax            ; point to the 0000 segment
  428.         mov    es,ax
  429.         mov    bx,(EMM*4)+2        ; find the EMM interrupt
  430.         mov    ax,es:[bx]
  431.         mov    es,ax            ; point to the EMM device
  432.         mov    di,10            ; header
  433.  
  434.         mov    si,offset EMMIDString    ; point to the EMM identifier
  435.         mov    cx,8
  436.     repz    cmpsb                ; compare a bunch of bytes
  437.         pop    es
  438.         jz    EMMPresent
  439.  
  440.         mov    dx,offset NoEMMThere    ; point to our error
  441.         jmp    InitFail        ;  the EMM isn't there!!
  442.  
  443. EMMPresent:    mov    ah,E_PageBase        ; get the page base
  444.         int    EMM
  445.         or    ah,ah
  446.         jne    GenFail
  447.  
  448.         mov    EMSBase,bx        ; store it
  449.  
  450.         mov    ah,E_Counts        ; get count of pages available
  451.         int    EMM
  452.         or    ah,ah
  453.         jne    GenFail
  454.  
  455.         cmp    bx,dx        ; is it all unused?
  456.         je    AllMine
  457.  
  458.         mov    dx,offset NotAllMem
  459.         jmp    InitFail
  460.  
  461. AllMine:    push     dx        ; save count
  462.  
  463.         mov    ah,E_Open    ; bx already has count
  464.         int    EMM
  465.         and    ah,ah
  466.         jne    GenFail
  467.  
  468.         mov    EMSHandle,dx    ; save the handle
  469.  
  470.         pop    cx        ; retrieve count
  471.  
  472. PageLoop:    push    cx
  473.         mov    ah,E_MapPage    ; map the current page
  474.         mov    al,0        ; into logical window 0
  475.         mov    bx,CurrentPage
  476.         mov    dx,EMSHandle
  477.         int    EMM
  478.         and    ah,ah
  479.         jne    GenFail
  480.  
  481.         call    PrintPage
  482.         call    TestPage    ; test a page
  483.         cmp    ax,0        ; is it zero?
  484.         je    NoError
  485.  
  486.         call    PrintError
  487.  
  488. NoError:    pop    cx
  489.  
  490.         mov    ah,CheckKeyboard    ; check for a keypress
  491.         int    21h
  492.         and    al,al        ; was there?
  493.         jne    fallout        ;  yep, get out of here
  494.  
  495.         inc    CurrentPage
  496.         loop    PageLoop
  497.  
  498.         mov    dx,offset TestedMsg    ; print end message
  499.         mov    ah,PrintString
  500.         int    21h
  501.  
  502. fallout:    mov    ah,E_Close    ; release the EMS memory we took
  503.         mov    dx,EMSHandle
  504.         int    EMM
  505.         and    ah,ah
  506.         jne    GenFail
  507.  
  508. endit:        les    bx,cs:RBPoint    ; get ES:BX back
  509.         xor    ax,ax
  510.         mov    rq.ndadro,ax    ;ending address is CS:0000
  511.         mov    rq.units,al    ;don't take any unit numbers
  512.  
  513.         mov    ax,cs
  514.         mov    rq.ndadrs,ax
  515.  
  516.         ret            ; return to the dispatcher routine
  517.  
  518. GenFail:    mov    dx,offset EMMError
  519.  
  520. InitFail:    push    dx
  521.         mov    dx,offset General    ;print error header
  522.         mov    ah,PrintString
  523.         int    21h
  524.         pop    dx
  525.  
  526.         mov    ah,PrintString        ; and then the error itself
  527.         int    21h
  528.         jmp    endit
  529.  
  530. Init        endp
  531.  
  532. ; ---------------------------------------------------------------------------
  533. ;  BIN2DEC
  534.  
  535. ;  This routine converts a binary number, in AX:BX, to decimal notation.
  536. ;  It will convert up to 8 digits, and will supress leading zeros.  The
  537. ;  routine should be called with DS:SI set to point to the area to store
  538. ;  the converted number.
  539.  
  540. Bin2Dec        proc    near
  541.  
  542.         push    es        ; save the registers
  543.         push    ds
  544.         push    di
  545.         push    si
  546.  
  547.         mov    WorkAreaL,bx
  548.         mov    WorkAreaH,ax    ; put the number on our scratchpad
  549.  
  550.         mov    ax,ds        ; point to the answer with ES:DI
  551.         mov    es,ax
  552.         mov    di,si
  553.         add    di,7
  554.  
  555.         mov    si,offset WorkAreaL    ; point at scratchpad
  556.  
  557. Bin2DecLoop:    push    si
  558.  
  559.         xor    bx,bx        ; done flag
  560.         mov    cx,2        ; 2 words in our number
  561.         mov    dx,bx        ; clear remainder
  562.         add    si,2        ; point to the high end
  563.  
  564. Bin2DecDigit:    push    cx        ; save word count
  565.         mov    ax,[si]        ; get the digit
  566.         mov    cx,10
  567.         div    cx        ; convert it
  568.         mov    [si],ax        ; store it back
  569.         or    bx,ax        ; set the done flag appropriately
  570.         sub    si,2        ; point to next lower
  571.         pop    cx
  572.         loop    Bin2DecDigit
  573.  
  574.         or    dl,'0'        ; make it into a decimal digit
  575.         mov    [di],dl        ; and store it
  576.         dec    di        ; adjust pointer
  577.  
  578.         pop    si        ; get the pointer back
  579.         and    bx,bx        ; is the result zero?
  580.         jne    Bin2DecLoop    ; nope!  Do more!
  581.  
  582.         pop    si        ; retrieve the used registers
  583.         pop    di
  584.         pop    ds
  585.         pop    es
  586.         ret
  587.  
  588. WorkAreaL    dw    0        ; low end of the work area
  589. WorkAreaH    dw    0        ; high side of the work area
  590.  
  591. Bin2Dec        endp
  592.  
  593. ; ---------------------------------------------------------------------------
  594.  
  595. EMSHandle    dw    ?        ; our EMS handle number
  596. EMSBase        dw    ?        ; base segment of EMS
  597. CurrentPage    dw    ?        ; current page that we're testing
  598.  
  599. TestingMsg    db    'Page '
  600. TestingSpot    db    '         tested',cr,eos
  601.  
  602. TestedMsg    db    'All Pages Tested!     ',cr,lf,eos
  603.  
  604. ErrorMsg    db    'Error on Page '
  605. ErrorSpot    db    '        !',bell,cr,lf,eos
  606.  
  607. Banner        db    lf,"Nifty James' Famous EMS Memory Tester",cr,lf
  608.         db    "Version 1.00 of 21 Oct 1987",cr,lf
  609.     ifdef    V286
  610.         db    "Enhanced Processor Version",cr,lf
  611.     endif
  612.         db    lf,eos
  613.  
  614. EMMIDString    db    'EMMXXXX0'
  615.  
  616. General        db    'Device not installed.',cr,lf,eos
  617.  
  618. NoEMMThere    db    'The EMM is not installed.',cr,lf,lf,eos
  619.  
  620. EMMError    db    'EMM failure during testing.',cr,lf,lf,eos
  621.  
  622. NotAllMem    db    'EMM Memory not entirely empty.',cr,lf,lf,eos
  623.  
  624. tester        ends
  625.         end
  626.  
  627.