home *** CD-ROM | disk | FTP | other *** search
- ;******************************************************************************
- ;MEMTEST1.ASM for CP/M-80. Written by Len Moskowitz and released to the
- ;public domain. October 1984
- ;
- ; MEMTEST is a memory test program. It tests memory with
- ; twelve different patterns of bits. It does each test addressed
- ; both forwards and backwards through memory.
- ; The twelve patterns are:
- ;
- ; Bit 76543210
- ; ------------
- ; Pattern 0. 00000000 (00h, All zeros)
- ; 1. 00000001 (01h)___
- ; 2. 00000010 (02h) |
- ; 3. 00000100 (04h) |
- ; 4. 00001000 (08h) | "Walking Ones" or
- ; 5. 00010000 (10h) | "Barber Pole" pattern
- ; 6. 00100000 (20h) |
- ; 7. 01000000 (40h) |
- ; 8. 10000000 (80h)__|
- ; 9. 01010101 (55h, Even alternating ones)
- ; 10. 10101010 (AAh, Odd alternating ones)
- ; 11. 11111111 (FFh, All ones)
- ;
- ; Before the test begins, the program tells you where it resides
- ; so that you can avoid overwriting it. You are then prompted for
- ; whether you want screen updates and for the first and last addresses
- ; of the memory block to be tested. Screen updates cause the program
- ; to run much, much slower than without updates. If you choose updates,
- ; the screen will show the current address being tested and the pattern
- ; being used. The program expects the addresses to be in Hex
- ; (radix 16) format. A control C aborts the program.
- ; For each pattern, the first memory location is written to and
- ; then read from. The value read from memory is compared to the test
- ; pattern. If they are identical, the test proceeds to the next memory
- ; location. If they are not the same, the address that failed is
- ; displayed along with the current test pattern and the erroneous value
- ; that the memory location contained. You are given a choice of
- ; continuing or quitting.
- ; When all the locations are tested, the test goes on to the next
- ; pattern. When all twelve patterns have been tested using forward
- ; addressing (from low address to high address), the twelve are then
- ; repeated using backward addressing (high address to low address).
- ; If the test completes without mishap, a message confirms this and
- ; the program exits to CP/M (provided you haven't overwritten it with
- ; the test) via a jump to location 0000.
- ; I have provided for I/O using either the standard BDOS calls
- ; or direct console I/O via routines internal to MEMTST. This version
- ; has the internal routines commented out so that the casual user can
- ; run it without change. If you wish to make this test able to
- ; check all memory except for the block where it resides, all console
- ; I/O should be done using the internal routines. To activate them,
- ; comment out the BDOS subroutines and remove the comment semicolons
- ; from the internal subroutines. You also must change the
- ; "instatusport", "outstatusport", "inreadymask", "outreadymask",
- ; "indataport", and "outdataport" equates to reflect your system
- ; requirements.
- ; If you use the BDOS calls, take pains not to ask MEMTST to test
- ; the locations where the BDOS and BIOS reside. You can find the
- ; address of the BDOS by looking at locations 0006 and 0007 for a
- ; standard CP/M installation. (Location 0005 is the "jump to BDOS" call
- ; address.) Testing these locations will result in an overwrittten
- ; operating system and you'll have to reboot to bring the system back up.
- ; Also be sure not to ask to test the memory where MEMTST resides.
- ; For 64K of memory, the test takes approximately 75 seconds to
- ; complete on a 4 megaHertz Z80A system with no wait states with no
- ; screen updates. With screen updates on, the test takes 20 Hours!
- ; I therefore recommend you run without screen updates if you're testing
- ; any block sized over 0200h. If an error occurs, probe that area
- ; with updates on.
- ; A shortcoming of any test program of this type is that it can't
- ; test the worst case memory access timing required for instruction
- ; fetch operations. If you find you have problems that this program does
- ; not isolate, try using WORM (of which the current version is WORM21),
- ; which is available via many RCPM systems. It checks for access
- ; timing sensitivity but does not do exhaustive pattern testing. Between
- ; the two programs you're likely to uncover any memory problems you might
- ; have.
- ;
- ; Len Moskowitz
- ; Fair Lawn, N.J.
- ; October 1984
- ;
- ;11Nov84 Renamed MEMTST10.ASM to MEMTEST1 to avoid confusion
- ; with MEMTST11.ASM written by J. Kravitz, 08Dec76.
- ; Ken Stritzel, Flanders, NJ RCPM
- ;
- ;******************************************************************************
- ;
- ;****************
- ;***** Equates *
- ;****************
-
- cpm: equ 0000h ;jump to CP/M address
- bdos: equ 0005h ;jump to BDOS address
- conout: equ 02h ;BDOS console out function code
- conin: equ 01h ;BDOS console in function code
- constat: equ 0bh ;BDOS get console status code
- tpa: equ 0100h ;CP/M programs start at this address
- cr: equ 0dh ;ASCII carriage return
- lf: equ 0ah ;ASCII line feed
- controlc: equ 03h ;ASCII control C
- del: equ 7fh ;ASCII delete
- no: equ 0
- yes equ 0ffh
-
- ; Change the following equates to match your system if you are using the
- ; internal I/O subroutines. If you are using the CP/M BDOS calls you may
- ; leave these as is.
-
- outdataport: equ 0
- indataport: equ 0
- outstatusport: equ 1
- instatusport: equ 1
- outreadymask: equ 01
- inreadymask: equ 02
-
-
- memtst: org tpa
-
- ; Tell him where this program resides so he can avoid it during the test.
-
- lxi sp,stacktop
- lxi h,offlimits
- call print
- lxi h,repeat
- mov c,h
- call unpack
- mov c,l
- call unpack
- lxi h,andmessage
- call print
- lxi h,endprogram
- mov c,h
- call unpack
- mov c,l
- call unpack
- mvi a,'.'
- call sout
-
- ; Ask him if he wants the screen updated continuously, and store his
- ; answer in "screenupdate".
-
- lxi h,screenupdateQ
- call print
- call sin
- cpi 'Y'
- jz setupdateyes
- cpi 'y'
- jz setupdateyes
- cpi cr
- jz setupdateyes
- setupdateno: mvi a,no
- sta screenupdate
- jmp locationprompt
- setupdateyes: mvi a,yes
- sta screenupdate
-
- ; This section does initialization and gets the starting and ending
- ; locations from the fellow at the keyboard.
-
- locationprompt: lxi h,enterfirst
- call print
- call loca
- shld startloc
- lxi h,enterlast
- call print
- call loca
- call crlf
- mov e,l
- mov d,h
- inx d
- mvi a,0
- lxi h,step
- mov m,a
- inx h
- mov m,a
- lhld startloc
- mov c,a
- mov b,a
-
- ; This is the core of the memory test routine. The section from
- ; "repeat" to "doit" does the screen update if requested.
-
- repeat: lda screenupdate
- cpi no
- jz doit
- push b
- push h
- lxi h,currentaddress
- call print
- pop h
- push h
- mov c,h
- call unpack
- mov c,l
- call unpack
- lxi h,currentpattern
- call print
- pop h
- pop b
- push b
- push h
- mov c,b
- call unpack
- mvi a,cr
- call sout
- pop h
- pop b
-
- ; The next four lines do the memory test
-
- doit: mov m,b ;move the pattern to memory
- mov a,m ;move it back to A
- cmp b ;compare it back to the pattern
- jnz error ;jump if they don't match
-
- ; Check if he wants to exit and get the next test location ready.
-
- reenter: call consolestatus ;check if he pressed a key
- jz nocontrolc ;if not jump around the next few lines
- call sin ;if he did, take the character in
- ;SIN exits if it was control C
- nocontrolc: lda step ;check the "backward" flag
- ani 80h ;if it's set
- jnz backwards ; jump around the forward code
- inx h ;we're going forward so increment HL
- jmp compareend ; and jump around the backward code
- backwards: dcx h ;we're going backward so decrement HL
-
- ; This section checks the next address to be tested with the end
- ; location. If we haven't hit the end location yet, we loop to repeat.
- ; If we have hit it we fall through.
-
- compareend: mov a,l
- cmp e
- jnz repeat
- mov a,h
- cmp d
- jnz repeat
-
- ; See if we've completed the last pattern. If we have, then jump
- ; to "checkforback" to see if we've done the backward addressing yet.
- ; If this is not the last pattern, go onto the next one by incrementing
- ; the step counter in register C and STEP (which holds the step and the
- ; "backward" flag.
-
- checkstep: mvi a,0bh
- cmp c
- jz checkforback
- inr c
- lda screenupdate
- cpi no
- jz noupdate
- call crlf
- noupdate: lxi h,step
- mvi a,80h
- ana m
- jz backflagnotset
- mvi a,80h
- ora c
- mov m,a
- jmp setnewpattern
- backflagnotset: mov m,c
-
- ; Check what step we're going to do and set the new pattern accordingly.
-
- setnewpattern: mvi a,1
- cmp c
- jnz not1
- mvi b,1
- jmp loadpattern
- not1: mvi a,9h
- cmp c
- jnz not9
- mvi b,0aah
- jmp loadpattern
- not9: jnc lessthan9
- mvi a,0ah
- cmp c
- jnz not10mustbe11
- mvi b,55h
- jmp loadpattern
- not10mustbe11: mvi b,0ffh
- jmp loadpattern
- lessthan9: mov a,b
- rlc
- mov b,a
- loadpattern: lxi h,pattern
- mov m,b
- lhld startloc
- jmp repeat
-
- ; We get to this next section when we've completed the last pattern. If
- ; the "backward" flag (bit 7 of STEP) is not set, it sets it, swaps the
- ; starting and ending locations and starts the background addressing
- ; cycle. If the flag was set, we're done so we exit via ENDOK
-
- checkforback: lda screenupdate
- cpi no
- jz updateno
- call crlf
- updateno: lda step
- ani 80h
- jnz endok
- mvi a,80h
- sta step
- lxi h,startloc
- mov e,m
- inx h
- mov d,m
- dcx d
- lhld endloc
- shld startloc
- mvi a,0
- mov c,a
- mov b,a
- jmp repeat
-
- ; ENDOK prints the message "OK" and exits to CP/M.
-
- endok: call crlf
- mvi a,'O'
- call sout
- mvi a,'K'
- call sout
- jmp cpm
-
- ; ERROR prints the address of the memory cell that read back erroneous
- ; data, the expected pattern and the bad data. It then offers you
- ; the choice of continuing or exiting to CP/M.
-
- error: call crlf
- mov d,a
- push psw
- push b
- push d
- push h
- lxi h,errorat
- call print
- pop h
- push h
- mov c,h
- call unpack
- mov c,l
- call unpack
- lxi h,patternis
- call print
- mov c,b
- call unpack
- lxi h,memoryvalue
- call print
- mov c,d
- call unpack
- call crlf
- lxi h,continueQ
- call print
- call sin
- cpi 'Y'
- jz setuptorepeat
- cpi 'y'
- jz setuptorepeat
- cpi cr
- jz setuptorepeat
- jmp cpm
- setuptorepeat: mvi a,cr
- call sout
- pop h
- pop d
- pop b
- pop psw
- jmp reenter
-
- ;****************
- ;***** MESSAGES *
- ;****************
- ;
- errorat: db ' *** Error at location : ',0
- patternis: db ' Pattern is : ',0
- memoryvalue: db ' Memory value is : ',0
- continueQ db 'Continue? (Y/N) : ',0
- enterfirst: db cr,lf,'Enter first address : ',0
- enterlast: db cr,lf,'Enter last address : ',0
- currentaddress: db 'Current address : ',0
- currentpattern: db ' Current pattern : ',0
- screenupdateQ: db cr,lf,'Screen updates? (Runs much slower with updates'
- db ') (Y/N) : ',0
- offlimits: db cr,lf,'The core of this program resides between ',0
- andmessage: db ' and ',0
-
- ;*******************
- ;***** SUBROUTINES *
- ;*******************
-
- ; CONSOLESTATUS checks to see if a key was pressed. If a key was
- ; pressed, the A register will contain 0FFh. Otherwise it will have
- ; 00h.
-
- ; ***** BDOS I/O routine
-
- consolestatus: push b
- push d
- push h
- mvi c,constat
- call bdos
- ora a
- pop h
- pop d
- pop b
- ret
-
- ; ***** Internal I/O routine
- ;
- ;consolestatus: in instatusport
- ; ani inreadymask
- ; jz notready
- ; mvi a,0ffh
- ; ret
- ; notready:mvi a,0
- ; ret
- ;
- ;
- ; CRLF prints a carriage return and a line feed. Preserves all
- ; registers.
-
- crlf: push psw
- xra a
- adi cr
- call sout
- adi lf
- call sout
- pop psw
- ret
-
- ; HXTOASCI converts the lower nibble of the value in the A register
- ; into an ASCII numeric or alphabetic character. It expects the most
- ; significant nibble to be zeroed.
-
- hxtoasci: cpi 0ah
- jc numeric
- sui 9
- adi 40h
- ret
- numeric:adi 30h
- ret
-
- ; PRINT prints the string pointed to by registers HL until a zero
- ; (0h) is encountered.
- ;
- print: mov a,m
- cpi 0
- rz
- print1: call sout
- inx h
- mov a,m
- cpi 0
- jnz print1
- ret
-
- ; SIN gets one character from the console and echoes it back to the
- ; console. Character ends up in register A.
- ;
- ; ***** BDOS I/O version
-
- sin: push b
- push d
- push h
- mvi c,conin
- call bdos
- cpi controlc
- jz cpm
- pop h
- pop d
- pop b
- ret
-
- ; ***** Internal I/O version
-
- ;sin: in instatusport
- ; ani inreadymask
- ; jz sin
- ; in indataport
- ; cpi controlc
- ; jz cpm
- ; push psw
- ; call sout
- ; pop psw
- ; ret
-
- ; SOUT outputs whatever is the A register to the console. Returns with
- ; register A cleared to zero.
- ;
- ; ***** BDOS I/O version
-
- sout: push b
- push d
- push h
- mov e,a
- mvi c,conout
- call bdos
- pop h
- pop d
- pop b
- xra a
- ret
-
- ; ***** Internal I/O version
-
- ;sout: push psw
- ; sout1: in outstatusport
- ; ani outreadymask
- ; jz sout1
- ; pop psw
- ; out outdataport
- ; xra a
- ; ret
-
- ; UNPACK takes what ever is in register C (which is supposed to be
- ; an address or memory pattern), unpacks it into two hex digits,
- ; converts them to ASCII and outputs them to the console. Modifies
- ; A register only.
-
- unpack: mov a,c
- ani 0f0h
- rrc
- rrc
- rrc
- rrc
- call hxtoasci
- call sout
- mov a,c
- ani 0fh
- call hxtoasci
- call sout
- ret
-
- ;***************
- ;***** STORAGE *
- ;***************
- ; Storage goes here. The subroutines after this section can be written
- ; over by MEMTST if you want to test those locations. They are only
- ; used in the initialization section at the top of the program.
-
- screenupdate ds 1
- endloc: ds 2
- startloc: ds 2
- step: ds 1
- pattern: ds 1
- stack: ds 32
- stacktop: equ $
- endprogram: equ $
-
- ; LOCA takes four ASCII characters in from the console (expecting them
- ; to be 0-9 or A-F), converts them to hex, packs them into two bytes,
- ; and stores them in "endloc" and registers HL.
-
- loca: call sin
- call pack
- mov h,c
- call sin
- call pack
- mov l,c
- shld endloc
- ret
-
- ; PACK expects an ASCII character in register A. If it's an alphabetic
- ; character (A-F) it converts it to a hex digit in the range of A hex
- ; to F hex. If it is a number it just strips off the most significant
- ; nibble leaving a hex digit in the range from 0 to 9.
-
- pack: cpi 41h
- jc label8
- adi 09h
- label8: ani 0fh
- add a
- add a
- add a
- add a
- mov c,a
- call sin
- cpi del
- jnz norubout
- adi ' '
- call sout
- call sin
- jmp pack
- norubout: cpi 41h
- jc label9
- adi 09h
- label9: ani 0fh
- add c
- mov c,a
- ret