home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / memtest / memtest1.lbr / MEMTEST1.AQM / MEMTEST1.ASM
Assembly Source File  |  1985-02-09  |  15KB  |  594 lines

  1. ;******************************************************************************
  2. ;MEMTEST1.ASM for CP/M-80. Written by Len Moskowitz and released to the
  3. ;public domain. October 1984
  4. ;
  5. ;         MEMTEST is a memory test program.  It tests memory with
  6. ;    twelve different patterns of bits.  It does each test addressed
  7. ;    both forwards and backwards through memory.
  8. ;         The twelve patterns are:
  9. ;
  10. ;            Bit 76543210
  11. ;            ------------
  12. ;        Pattern    0.  00000000 (00h, All zeros)
  13. ;            1.  00000001 (01h)___
  14. ;            2.  00000010 (02h)  |
  15. ;            3.  00000100 (04h)  |
  16. ;            4.  00001000 (08h)  | "Walking Ones" or
  17. ;            5.  00010000 (10h)  | "Barber Pole" pattern    
  18. ;            6.  00100000 (20h)  |
  19. ;            7.  01000000 (40h)  |
  20. ;            8.  10000000 (80h)__|  
  21. ;                   9.  01010101 (55h, Even alternating ones)
  22. ;            10. 10101010 (AAh, Odd alternating ones)
  23. ;            11. 11111111 (FFh, All ones)
  24. ;
  25. ;         Before the test begins, the program tells you where it resides
  26. ;    so that you can avoid overwriting it.  You are then prompted for 
  27. ;    whether you want screen updates and for the first and last addresses 
  28. ;    of the memory block to be tested.  Screen updates cause the program
  29. ;    to run much, much slower than without updates.  If you choose updates,
  30. ;    the screen will show the current address being tested and the pattern
  31. ;    being used.  The program expects the addresses to be in Hex
  32. ;    (radix 16) format.  A control C aborts the program.
  33. ;         For each pattern, the first memory location is written to and
  34. ;    then read from.  The value read from memory is compared to the test
  35. ;    pattern. If they are identical, the test proceeds to the next memory
  36. ;    location.  If they are not the same, the address that failed is 
  37. ;    displayed along with the current test pattern and the erroneous value 
  38. ;    that the memory location contained. You are given a choice of
  39. ;    continuing or quitting.
  40. ;         When all the locations are tested, the test goes on to the next 
  41. ;    pattern.  When all twelve patterns have been tested using forward
  42. ;    addressing (from low address to high address), the twelve are then
  43. ;    repeated using backward addressing (high address to low address).
  44. ;    If the test completes without mishap, a message confirms this and
  45. ;    the program exits to CP/M (provided you haven't overwritten it with
  46. ;    the test) via a jump to location 0000.
  47. ;         I have provided for I/O using either the standard BDOS calls 
  48. ;    or direct console I/O via routines internal to MEMTST.  This version
  49. ;    has the internal routines commented out so that the casual user can
  50. ;    run it without change.  If you wish to make this test able to 
  51. ;    check all memory except for the block where it resides, all console
  52. ;    I/O should be done using the internal routines.  To activate them,
  53. ;    comment out the BDOS subroutines and remove the comment semicolons
  54. ;    from the internal subroutines.  You also must change the 
  55. ;    "instatusport",    "outstatusport", "inreadymask", "outreadymask", 
  56. ;    "indataport", and "outdataport" equates to reflect your system
  57. ;    requirements.
  58. ;         If you use the BDOS calls, take pains not to ask MEMTST to test
  59. ;    the locations where the BDOS and BIOS reside.  You can find the
  60. ;    address of the BDOS by looking at locations 0006 and 0007 for a
  61. ;    standard CP/M installation. (Location 0005 is the "jump to BDOS" call
  62. ;    address.)  Testing these locations will result in an overwrittten
  63. ;    operating system and you'll have to reboot to bring the system back up.
  64. ;    Also be sure not to ask to test the memory where MEMTST resides.
  65. ;         For 64K of memory, the test takes approximately 75 seconds to 
  66. ;    complete on a 4 megaHertz Z80A system with no wait states with no
  67. ;    screen updates.  With screen updates on, the test takes 20 Hours!
  68. ;    I therefore recommend you run without screen updates if you're testing
  69. ;    any block sized over 0200h.  If an error occurs, probe that area 
  70. ;    with updates on.
  71. ;         A shortcoming of any test program of this type is that it can't
  72. ;    test the worst case memory access timing required for instruction
  73. ;    fetch operations.  If you find you have problems that this program does
  74. ;    not isolate, try using WORM (of which the current version is WORM21),
  75. ;    which is available via many RCPM systems.  It checks for access
  76. ;    timing sensitivity but does not do exhaustive pattern testing.  Between
  77. ;    the two programs you're likely to uncover any memory problems you might
  78. ;    have.
  79. ;
  80. ;                        Len Moskowitz
  81. ;                        Fair Lawn, N.J.
  82. ;                        October 1984
  83. ;
  84. ;11Nov84  Renamed MEMTST10.ASM to MEMTEST1 to avoid confusion
  85. ;         with MEMTST11.ASM written by J. Kravitz, 08Dec76.
  86. ;         Ken Stritzel, Flanders, NJ  RCPM
  87. ;
  88. ;******************************************************************************
  89. ;
  90. ;****************
  91. ;*****  Equates *
  92. ;****************
  93.  
  94. cpm:        equ    0000h    ;jump to CP/M address
  95. bdos:        equ    0005h    ;jump to BDOS address
  96. conout:        equ    02h    ;BDOS console out function code
  97. conin:        equ    01h    ;BDOS console in function code
  98. constat:    equ    0bh    ;BDOS get console status code
  99. tpa:        equ    0100h    ;CP/M programs start at this address
  100. cr:        equ    0dh    ;ASCII carriage return
  101. lf:        equ    0ah    ;ASCII line feed
  102. controlc:    equ    03h    ;ASCII control C
  103. del:        equ    7fh    ;ASCII delete
  104. no:        equ    0
  105. yes        equ    0ffh
  106.  
  107. ; Change the following equates to match your system if you are using the 
  108. ; internal I/O subroutines.  If you are using the CP/M BDOS calls you may 
  109. ; leave these as is.
  110.  
  111. outdataport:    equ    0
  112. indataport:    equ    0
  113. outstatusport:    equ    1
  114. instatusport:    equ    1
  115. outreadymask:    equ    01
  116. inreadymask:    equ    02
  117.  
  118.  
  119. memtst:        org    tpa
  120.  
  121. ;    Tell him where this program resides so he can avoid it during the test.
  122.  
  123.         lxi    sp,stacktop
  124.         lxi    h,offlimits
  125.         call    print
  126.         lxi    h,repeat
  127.         mov    c,h
  128.         call    unpack
  129.         mov    c,l
  130.         call    unpack
  131.         lxi    h,andmessage
  132.         call    print
  133.         lxi    h,endprogram
  134.         mov    c,h
  135.         call    unpack
  136.         mov    c,l
  137.         call    unpack
  138.         mvi    a,'.'
  139.         call    sout
  140.  
  141. ;    Ask him if he wants the screen updated continuously, and store his
  142. ;    answer in "screenupdate".
  143.  
  144.         lxi    h,screenupdateQ
  145.         call    print
  146.         call    sin
  147.         cpi    'Y'
  148.         jz    setupdateyes
  149.         cpi    'y'
  150.         jz    setupdateyes
  151.         cpi    cr
  152.         jz    setupdateyes
  153. setupdateno:    mvi    a,no
  154.         sta    screenupdate
  155.         jmp    locationprompt
  156. setupdateyes:    mvi    a,yes
  157.         sta    screenupdate
  158.  
  159. ;    This section does initialization and gets the starting and ending 
  160. ;    locations from the fellow at the keyboard.
  161.  
  162. locationprompt:    lxi    h,enterfirst
  163.         call    print
  164.         call    loca
  165.         shld    startloc
  166.         lxi    h,enterlast
  167.         call    print
  168.         call    loca
  169.         call    crlf    
  170.         mov    e,l
  171.         mov    d,h
  172.         inx    d
  173.         mvi    a,0
  174.         lxi    h,step
  175.         mov    m,a
  176.         inx    h
  177.         mov    m,a
  178.         lhld    startloc
  179.         mov    c,a
  180.         mov    b,a
  181.  
  182. ;    This is the core of the memory test routine.  The section from
  183. ;    "repeat" to "doit" does the screen update if requested.
  184.  
  185. repeat:        lda    screenupdate
  186.         cpi    no
  187.         jz    doit
  188.         push    b
  189.         push    h
  190.         lxi    h,currentaddress
  191.         call    print
  192.         pop    h
  193.         push    h
  194.         mov    c,h
  195.         call    unpack
  196.         mov    c,l
  197.         call    unpack
  198.         lxi    h,currentpattern
  199.         call    print
  200.         pop    h
  201.         pop    b
  202.         push    b
  203.         push    h
  204.         mov    c,b
  205.         call    unpack
  206.         mvi    a,cr
  207.         call    sout
  208.         pop    h
  209.         pop    b
  210.  
  211. ;    The next four lines do the memory test
  212.  
  213. doit:        mov    m,b        ;move the pattern to memory
  214.         mov    a,m        ;move it back to A
  215.         cmp    b        ;compare it back to the pattern
  216.         jnz    error        ;jump if they don't match
  217.  
  218. ;    Check if he wants to exit and get the next test location ready.
  219.  
  220. reenter:     call    consolestatus    ;check if he pressed a key
  221.         jz    nocontrolc    ;if not jump around the next few lines
  222.         call    sin        ;if he did, take the character in
  223.                     ;SIN exits if it was control C
  224.     nocontrolc:    lda    step        ;check the "backward" flag
  225.         ani    80h        ;if it's set
  226.         jnz    backwards    ; jump around the forward code
  227.         inx    h        ;we're going forward so increment HL
  228.         jmp    compareend    ; and jump around the backward code
  229. backwards:    dcx    h        ;we're going backward so decrement HL
  230.  
  231. ;    This section checks the next address to be tested with the end 
  232. ;    location.  If we haven't hit the end location yet, we loop to repeat.
  233. ;    If we have hit it we fall through.
  234.  
  235. compareend:    mov    a,l
  236.         cmp    e
  237.         jnz    repeat
  238.         mov    a,h
  239.         cmp    d
  240.         jnz    repeat
  241.  
  242. ;    See if we've completed the last pattern.  If we have, then jump
  243. ;    to "checkforback" to see if we've done the backward addressing yet.
  244. ;    If this is not the last pattern, go onto the next one by incrementing
  245. ;    the step counter in register C and STEP (which holds the step and the
  246. ;    "backward" flag.
  247.  
  248. checkstep:    mvi    a,0bh
  249.         cmp    c
  250.         jz    checkforback
  251.         inr    c
  252.         lda    screenupdate
  253.         cpi    no
  254.         jz    noupdate
  255.         call    crlf
  256.       noupdate:    lxi    h,step
  257.         mvi    a,80h
  258.         ana    m
  259.         jz    backflagnotset
  260.         mvi    a,80h
  261.         ora    c
  262.         mov    m,a
  263.         jmp    setnewpattern
  264. backflagnotset:    mov    m,c
  265.  
  266. ;    Check what step we're going to do and set the new pattern accordingly.
  267.  
  268. setnewpattern:    mvi    a,1
  269.         cmp    c
  270.         jnz    not1
  271.         mvi    b,1
  272.         jmp    loadpattern
  273. not1:        mvi    a,9h
  274.         cmp    c
  275.         jnz    not9
  276.         mvi    b,0aah
  277.         jmp    loadpattern
  278. not9:        jnc    lessthan9
  279.         mvi    a,0ah
  280.         cmp    c
  281.         jnz    not10mustbe11
  282.         mvi    b,55h
  283.         jmp    loadpattern
  284. not10mustbe11:    mvi    b,0ffh
  285.         jmp    loadpattern
  286. lessthan9:    mov    a,b
  287.         rlc
  288.         mov    b,a
  289. loadpattern:    lxi    h,pattern
  290.         mov    m,b
  291.         lhld    startloc
  292.         jmp    repeat
  293.  
  294. ;    We get to this next section when we've completed the last pattern.  If
  295. ;    the "backward" flag (bit 7 of STEP) is not set, it sets it, swaps the
  296. ;    starting and ending locations and starts the background addressing
  297. ;    cycle.  If the flag was set, we're done so we exit via ENDOK
  298.  
  299. checkforback:    lda    screenupdate
  300.         cpi    no
  301.         jz    updateno
  302.         call    crlf
  303.      updateno:    lda    step
  304.         ani    80h
  305.         jnz    endok
  306.         mvi    a,80h
  307.         sta    step
  308.         lxi    h,startloc
  309.         mov    e,m
  310.         inx    h
  311.         mov    d,m
  312.         dcx    d
  313.         lhld    endloc
  314.         shld    startloc
  315.         mvi    a,0
  316.         mov    c,a
  317.         mov    b,a
  318.         jmp    repeat
  319.  
  320. ;    ENDOK prints the message "OK" and exits to CP/M.
  321.  
  322. endok:        call    crlf
  323.         mvi    a,'O'
  324.         call    sout
  325.         mvi    a,'K'
  326.         call    sout
  327.         jmp    cpm
  328.  
  329. ;    ERROR prints the address of the memory cell that read back erroneous
  330. ;    data, the expected pattern and the bad data.  It then offers you
  331. ;    the choice of continuing or exiting to CP/M.
  332.  
  333. error:        call    crlf
  334.         mov    d,a
  335.         push    psw
  336.         push    b
  337.         push    d
  338.         push    h
  339.         lxi    h,errorat
  340.         call    print
  341.         pop    h
  342.         push    h
  343.         mov    c,h
  344.         call    unpack
  345.         mov    c,l
  346.         call    unpack
  347.         lxi    h,patternis
  348.         call    print
  349.         mov    c,b
  350.         call    unpack
  351.         lxi    h,memoryvalue
  352.         call    print
  353.         mov    c,d
  354.         call    unpack
  355.         call    crlf
  356.         lxi    h,continueQ
  357.         call    print
  358.         call    sin
  359.         cpi    'Y'
  360.         jz    setuptorepeat
  361.         cpi    'y'
  362.         jz    setuptorepeat
  363.         cpi    cr
  364.         jz    setuptorepeat
  365.         jmp    cpm
  366. setuptorepeat:    mvi    a,cr
  367.         call    sout
  368.         pop    h
  369.         pop    d
  370.         pop    b
  371.         pop    psw
  372.         jmp    reenter
  373.  
  374. ;****************
  375. ;***** MESSAGES *
  376. ;****************
  377. ;
  378. errorat:    db    '  *** Error at location : ',0
  379. patternis:    db    '     Pattern is : ',0
  380. memoryvalue:    db    '     Memory value is : ',0
  381. continueQ    db    'Continue? (Y/N) : ',0 
  382. enterfirst:    db    cr,lf,'Enter first address : ',0
  383. enterlast:    db    cr,lf,'Enter last address : ',0
  384. currentaddress:    db    'Current address : ',0
  385. currentpattern:    db    '     Current pattern : ',0
  386. screenupdateQ:    db    cr,lf,'Screen updates? (Runs much slower with updates'
  387.         db    ') (Y/N) : ',0
  388. offlimits:    db    cr,lf,'The core of this program resides between ',0
  389. andmessage:    db    ' and ',0
  390.  
  391. ;*******************
  392. ;***** SUBROUTINES *
  393. ;*******************
  394.  
  395. ;    CONSOLESTATUS checks to see if a key was pressed.  If a key was
  396. ;    pressed, the A register will contain 0FFh.  Otherwise it will have
  397. ;    00h.
  398.  
  399. ;    ***** BDOS I/O routine
  400.  
  401. consolestatus:    push    b
  402.         push    d
  403.         push    h
  404.         mvi    c,constat
  405.         call    bdos
  406.         ora    a
  407.         pop    h
  408.         pop    d
  409.         pop    b
  410.         ret
  411.  
  412. ;    ***** Internal I/O routine
  413. ;
  414. ;consolestatus:    in    instatusport
  415. ;        ani    inreadymask
  416. ;        jz    notready
  417. ;        mvi    a,0ffh
  418. ;        ret
  419. ;      notready:mvi    a,0
  420. ;        ret
  421. ;
  422. ;
  423. ;    CRLF prints a carriage return and a line feed. Preserves all
  424. ;    registers.
  425.  
  426. crlf:        push    psw
  427.         xra    a
  428.         adi    cr
  429.         call    sout        
  430.         adi    lf
  431.         call    sout
  432.         pop    psw
  433.         ret
  434.  
  435. ;    HXTOASCI converts the lower nibble of the value in the A register
  436. ;    into an ASCII numeric or alphabetic character.  It expects the most
  437. ;    significant nibble to be zeroed.
  438.  
  439. hxtoasci:    cpi    0ah
  440.         jc    numeric
  441.         sui    9
  442.         adi    40h
  443.         ret
  444.     numeric:adi    30h
  445.         ret
  446.  
  447. ;    PRINT prints the string pointed to by registers HL until a zero
  448. ;    (0h) is encountered.
  449. ;
  450. print:        mov    a,m
  451.         cpi    0
  452.         rz
  453.     print1:    call    sout
  454.         inx    h
  455.         mov    a,m
  456.         cpi    0
  457.         jnz    print1
  458.         ret
  459.  
  460. ;    SIN gets one character from the console and echoes it back to the 
  461. ;    console.  Character ends up in register A.
  462. ;
  463. ;    ***** BDOS I/O version
  464.  
  465. sin:        push    b
  466.         push    d
  467.         push    h
  468.         mvi    c,conin
  469.         call    bdos
  470.         cpi    controlc
  471.         jz    cpm
  472.         pop    h
  473.         pop    d
  474.         pop    b
  475.         ret
  476.  
  477. ;    ***** Internal I/O version
  478.  
  479. ;sin:        in    instatusport
  480. ;        ani    inreadymask
  481. ;        jz    sin
  482. ;        in    indataport
  483. ;        cpi    controlc
  484. ;        jz    cpm
  485. ;        push    psw
  486. ;        call    sout
  487. ;        pop    psw
  488. ;        ret
  489.  
  490. ;    SOUT outputs whatever is the A register to the console.  Returns with
  491. ;    register A cleared to zero.
  492. ;
  493. ;    ***** BDOS I/O version
  494.  
  495. sout:        push    b
  496.         push    d
  497.         push    h
  498.         mov    e,a
  499.         mvi    c,conout
  500.         call    bdos
  501.         pop    h
  502.         pop    d
  503.         pop    b
  504.         xra    a
  505.         ret
  506.  
  507. ;    ***** Internal I/O version
  508.  
  509. ;sout:        push    psw
  510. ;    sout1:    in    outstatusport
  511. ;        ani    outreadymask
  512. ;        jz    sout1
  513. ;        pop    psw
  514. ;        out    outdataport
  515. ;        xra    a
  516. ;        ret
  517.  
  518. ;    UNPACK takes what ever is in register C (which is supposed to be
  519. ;    an address or memory pattern), unpacks it into two hex digits, 
  520. ;    converts them to ASCII and outputs them to the console.  Modifies
  521. ;    A register only.
  522.  
  523. unpack:        mov    a,c
  524.         ani    0f0h
  525.         rrc
  526.         rrc
  527.         rrc
  528.         rrc
  529.         call    hxtoasci
  530.         call    sout
  531.         mov    a,c
  532.         ani    0fh
  533.         call    hxtoasci
  534.         call    sout
  535.         ret
  536.  
  537. ;***************
  538. ;***** STORAGE *
  539. ;***************
  540. ;    Storage goes here.  The subroutines after this section can be written 
  541. ;    over by MEMTST if you want to test those locations.  They are only 
  542. ;    used in the initialization section at the top of the program.
  543.  
  544. screenupdate    ds    1
  545. endloc:        ds    2
  546. startloc:    ds    2
  547. step:        ds    1
  548. pattern:    ds    1
  549. stack:        ds    32
  550. stacktop:    equ    $
  551. endprogram:    equ    $
  552.  
  553. ;    LOCA takes four ASCII characters in from the console (expecting them
  554. ;    to be 0-9 or A-F), converts them to hex, packs them into two bytes,
  555. ;    and stores them in "endloc" and registers HL.
  556.  
  557. loca:        call    sin
  558.         call    pack
  559.         mov    h,c
  560.         call    sin
  561.         call    pack
  562.         mov    l,c
  563.         shld    endloc
  564.         ret
  565.  
  566. ;    PACK expects an ASCII character in register A.  If it's an alphabetic
  567. ;    character (A-F) it converts it to a hex digit in the range of A hex 
  568. ;    to F hex.  If it is a number it just strips off the most significant
  569. ;    nibble leaving a hex digit in the range from 0 to 9.
  570.  
  571. pack:        cpi    41h
  572.         jc    label8
  573.         adi    09h
  574.     label8:    ani    0fh
  575.         add    a
  576.         add    a
  577.         add    a
  578.         add    a
  579.         mov    c,a
  580.         call    sin
  581.         cpi    del
  582.         jnz    norubout
  583.         adi    ' '
  584.         call    sout
  585.         call    sin
  586.         jmp    pack
  587.       norubout:    cpi    41h
  588.         jc    label9
  589.         adi    09h
  590.     label9:    ani    0fh
  591.         add    c
  592.         mov    c,a
  593.         ret
  594.