DOCUMENTATION FOR MEMRS.COM Introduction ------------ MEMRS is an exhaustive memory test program for CP/M environments. It tests from the top of itself to the bottom of the CP/M BIOS or alternatively, the BDOS. Usage ----- MEMRS [-R][-B] Where [-R] is an optional "Random number only" test specifier [-B] is an optional "Test to BDOS" specifier Examples -------- MEMRS This will invoke the program with no special options. MEMRS -R This will invoke the program for the random number test only. MEMRS -B This will invoke the program for default testing to the bottom of the BDOS and use the BDOS for I/O rather than default test to the bottom of the BIOS and use the BIOS for I/O. MEMRS -BR or MEMRS -RB or MEMRS -B -R or MEMRS -R -B This will invoke the program for default testing to the bottom of the BDOS as above AND random number only test. Error Messages -------------- If any memory location fails any of the component parts of the memory test an error message will be displayed as follows:- LOCATION SHOULD BE WAS 6000 00 0000 0000 FF 1111 1111 If there are multiple bad memory locations up to 18 will be displayed before the display halts and prompts for a keypress to display further errors. LOCATION SHOULD BE WAS 7000 00 0000 0000 FF 1111 1111 7001 00 0000 0000 FF 1111 1111 7002 00 0000 0000 FF 1111 1111 7003 00 0000 0000 FF 1111 1111 7004 00 0000 0000 FF 1111 1111 7005 00 0000 0000 FF 1111 1111 7006 00 0000 0000 FF 1111 1111 7007 00 0000 0000 FF 1111 1111 7008 00 0000 0000 FF 1111 1111 7009 00 0000 0000 FF 1111 1111 700A 00 0000 0000 FF 1111 1111 700B 00 0000 0000 FF 1111 1111 700C 00 0000 0000 FF 1111 1111 700D 00 0000 0000 FF 1111 1111 700E 00 0000 0000 FF 1111 1111 700F 00 0000 0000 FF 1111 1111 7010 00 0000 0000 FF 1111 1111 7011 00 0000 0000 FF 1111 1111 "CR" to continue test - "SP", "^C" to quit, "^X" to restart. Internal Prompts ---------------- The program prompts for the starting and ending addresses of the block of memory to be tested and offers default values which will test the largest possible block of memory. The default top of the block to be tested depends on whether the -B option was specified. If the default values are chosen, the actual value determined by the program is displayed next to the prompt as if the user had entered the value. When specific values are entered by the user a valid 4 digit hexadecimal address must be given or an error message will be displayed and the prompt issued again. The program may be aborted at any time by hitting any of the keys specified in the abort prompt. The program prompts as follows:- MEMRS Memory Test - Version 1.9 BDOS located at D300 Top of memory at FFFF Press "SP" or "^C" to warm boot at any time or "^X" to restart test from beginning. Response of "CR" gives default test range which starts above this program and ends at BDOS Starting address (Hex or "CR") 08F7 Ending address (Hex or "CR") D3F9 "CR" to continue test - "SP", "^C" to quit, "^X" to restart. Tutorial on Memory Testing -------------------------- There is no practical way to do a thorough test on all of a computers memory in one pass. The memory test program itself will occupy some memory which it cannot thoroughly test. It is possible to write simple memory tests which are able to test the memory that the reside in but these tests will not detect many types of memory errors. Memory faults can be fairly simple gross errors where a bit is permanently stuck (high or low) or they may be timing/pattern sensitive where the fault is only evident with a certain combination of data in surrounding bits. To attempt to test memory as thoroughly as possible several different types of tests need to be performed. MEMRS has a wide variety of tests and has proven particularly effective in locating bad memory in comparison to large number of other memory test programs with which it has been compared. It does not perform any long term memory retention testing or any "burn in" testing, however these types of tests are best performed over long periods of time and require highly optimised programs to execute in realistic time spans. MEMRS is intended as a relatively fast but thorough test to quickly establish whether any of the more common memory errors has occured. In practical terms, the whole of a computer's memory rarely fails simultaneously. Memory failures generally occur in individual memory chips which usually cover no more than 16K of memory space (though this will change as 64K chips become readily available). In this case it is usually possible in CP/M systems to readdress memory so that the suspected bad memory is located in an area that can be tested with MEMRS. If the bad memory is located in any of the CP/M system areas it is highly unlikely that you will be able to reliably load any programs at all from disk so there is not a great deal of point in designing memory tests for these addresses. If an error is suspected in the CP/M BIOS memory area the best move is to build a smaller size CP/M system that does not use the suspected bad memory and the load MEMRS and test the suspect memory. MEMRS will test any address explicitly given to it. It does not test to see if you will kill CP/M or itself. The random number only test is useful for longer term testing of memory. If an intermittent fault is suspected and the memory has passed several "full" test cycles it is probably worthwhile stopping the test and restarting it as a random number only test which will cycle much faster. The normal default ending address of the bottom of the BIOS gives the largest possible block of memory to test. It also means that all console input and output from the program goes directly to the BIOS jump table so it is not possible to log the output on the printer using Control P. Specifying the BDOS option at invokation directs all console output via the BDOS which means typing Control P before the program is invoked. END OF MEMRS.DOC ################################################################# ;MEMR SEP 3, 1979 Page 0 VERS EQU 19 ;X.X ; ; ;Diss-assembly of Delta Products memory test program ;Written by D. Rasmussen January 1, 1979 ; ;Extensively re-written and new tests added by Larry Alkoff ; ;Additional changes by Bill Bolton ; ;******************************************** ; FIX LIST BY WFB ;******************************************** ;15/JULY/81 V19-OPTIONAL CONOUT VIA BDOS/BIOS ; AND NEW COMMAND LINE ARGUMENT ; TEST, COMMENT TEXT UPDATED ;14/JULY/81 V18-CONOUT VIA BDOS ;14/JULY/81 V17-MESSAGES CORRECTED ; ;******************************************** ; FIX LIST by LBA ;******************************************** ;9/3 V16-MISC CLEANUP ;6/11 V15-BUGF ANI 7FH IN HEATH CRTIN ;5/25 V14-MSGS, RANGE LIMITS, FIX S.B. TEST ;5/19 V13-CONDX FOR MONITOR I/O ;5/18 V12-IMPROVE WALKING BIT AND CHECKERBOARD TEST ;5/15 V11-BUGF CONO PRESERVE REGS ; AND DEFAULT END ADDR (DEFEND) NOW JUST BELOW BIOS ;5/13/79 V0-OBJECT CODE AND SOURCE LISTING ; GIVEN TO LA BY HEAD OF DELTA PRODUCTS ; AT SAN FRANCISCO COMPUTER FAIR. ; ;******************************************** ; INFORMATION ABOUT THIS TEST ;******************************************** ; ; This memory test will use default address ;if starting and ending address questions ;are answered with a "CR". ;Memory test can be terminated by a "SP". ; ;Command line arguments are accepted as follows - ; '-' start of argument string ; 'B' console output via BDOS (for spooling or printing) ; 'R' random number test only ; ;The arguments may be given separately or together, ;i.e. -B, -R, -BR, -RB, or even -B -R ;The default upper test boundary address is modifed ;to the bottom of the BDOS if the B option is given. ; ; This test is designed to display the most common ;problems first and most uncommon ones last. ;The test never finishes by itself. ;The operator may terminate by pressing the ;space bar at any time. ;Generally memory chip failures will be found within 5 seconds. ;The test takes about 3 minutes to run all ;phases in a 32k board. ; To completely test for all address open and short ;combinations, the test should be run over a 4K boundry. ;Then run the test over the full range. There are some ;subtle things that get missed if you only run the ;test over the full range and not 4K at a time. ; The test falls into a random numbers test at the end ;of the first phase and will stay there until ;a space bar is pressed. ;If the memory board passes these tests and will ;run for an hour on the random numbers test ;without a problem, look elsewhere for your troubles. ; ; ;The following tests are performed: ; ;FAST COMPLEMENT: ;This is a test of ALL MEMORY starting at 0 ;and testing to memtop (except its own loop). ;Pick up each byte, complement and try to store. ;Quickly test if properly complemented ;and restore original byte. ; ;STUCK BIT: ;1. Fills test area with 0FFH and checks for 0FFH. ;2. Then fills test area with 0's and tests for 0's. ;3. Then re-fills with 0FFH and tests ; just in case the bit was originally high in (1.). ; ;ADJACENT BIT SHORTED: ;Sets a single bit in all bytes high. ;This checks if a bit is shorted to the ;ones on each side. ;The test repeats 8 times, rotating ;the test bit from LSB to MSB. ; ;CHECKERBOARD: ;Fill memory with 0AAH, 55H pattern and check. ;This forms an alternating "checkerboard". ;Then reverse the pattern and re-check. ; ;WALKING BIT TEST: ;Fill memory with one bit set for each byte. ;The bit rotates at memory increases. ;For example, byte 1 has bit 1 set, byte 2 bit 2 etc. ;Then memory is checked for the proper pattern. ;This is repeated 8 times, rotating the bit each time. ;Then, the whole procedure is repeated rotating ;the opposite way. ; ;ADDRESS SHORTED: ;Fills all memory with 55H then writes an 0AAH ;at 0 (or the lowest memory tested). ;It then tests the rest of memory for 55H's. ;Then it clears location of the 0AAH and ;writes it into location 1. ;Then does same with location 2,4,8,etc setting ;a new address bit high each time and testing all of memory. ;If any address bit is shorted to another, ;the test will find an 0AAH in another location ;than the place it wrote one. ;This test takes the most time and is run last. ; ;RANDOM NUMBERS: ;A random number routine generates an 8 bit number ;pattern and writes it through all test memory. ;It then re-inserts the same seed to the routine ;and test reads the memory. A new seed is generated ;and the exercise is repeated with a new pattern. ;This goes on and on reporting each loop through ;until terminated with the space bar. ; ; ;******************************************** ; SWITCHES ;******************************************** ; TRUE EQU 0FFFFH FALSE EQU NOT TRUE ; NOCHEK EQU FALSE ;NO RANGE CHECKING HEATH EQU FALSE CRAM EQU 4200H AND HEATH ;CP/M RAM BASE (0=STANDARD) ; ; PICK ONE I/O ROUTINE ; CPMIO EQU TRUE ;I/O VIA CP/M, WARM BOOT EXIT LAPIO EQU FALSE ;I/O VIA LAPPLE H84CRT EQU FALSE ;HEATH ROUTINE ; ;******************************************** ; EQUATES ;******************************************** ; DEFST EQU 500H ;DEFAULT STARTING ADDR (INCLUSIVE) DEFEND EQU 0F5FFH ;DEFAULT ENDING ADDR (INCLUSIVE) TPA EQU CRAM+100H STACK EQU CRAM+100H ;STACK RETRYS EQU 18 ;# OF RETRYS ENDADD EQU STACK-2 ;ENDING ADDRESS MEM EQU STACK-4 ;STARTING ADDRESS MEMTOPL EQU STACK-6 ;STORE TOP OF MEMORY COUNT EQU STACK-7 ;STORAGE FOR RETRY COUNT TESTBYTE EQU STACK-8 ;STORAGE TBUF EQU CRAM+82H ;OR STACK-9 IF NOT CP/M TBUFF SEED EQU STACK-11 SEEDST EQU STACK-13 TEMP EQU STACK-15 WBOOT EQU CRAM+0 ;WARM BOOT ENTRY BDOS EQU CRAM+5 ;BDOS ENTRY CR EQU 0DH LF EQU 0AH BD$OFF EQU -7 ;OFFSET TO BELOW BDOS BI$OFF EQU -4 ;OFFSET TO BELOW BIOS ; ;******************************************** ; START OF PROGRAM ;******************************************** ; ORG TPA ; START: JMP START2 ; JEXIT: JMP MONIT JCONI: JMP CONIN ;JUMPS MAY BE PATCHED JCONS: JMP CONST JCONO: JMP CONOUT ; ;******************************************** ; MAIN LOOP ;******************************************** ; START2: LXI SP,STACK-16 CALL INIT MVI A,RETRYS ;SET RETRY COUNT STA COUNT LXI D,SIG ;SIGN ON CALL PMSG ;PRINT IT CALL CRLF CALL CRLF LDA BDOS$FLAG ORA A ;BIOS OUTPUT JNZ BDOS$1 ;NO LXI D,BIOSMSG CALL PMSG LXI D,LOCMSG CALL PMSG LHLD WBOOT+1 ;GET LOCATION OF BIOS ENTRY LXI D,BI$OFF+1 ;OFFSET TO START OF BIOS DAD D MVI L,0 JMP GO$ON$1 ; BDOS$1: LXI D,BDOSMSG CALL PMSG LXI D,LOCMSG CALL PMSG LHLD BDOS+1 ;GET LOCATION OF BDOS ENTRY LXI D,BD$OFF+1 ;OFFSET TO START OF BDOS DAD D MVI L,0 GO$ON$1: CALL PHL ;PRINT LOCATION OF BIOS LXI D,MEMSG CALL PMSG CALL MEMTOP ;FIND TOP OF MEMORY SHLD MEMTOPL ;AND SAVE CALL PHL ;AND PRINT IT LXI D,SPMSG CALL PMSG LXI D,XPMSG ;EXPLAIN CALL PMSG LDA BDOS$FLAG ORA A ;BIOS OUTPUT? JNZ BDOS$4 ;NO LXI D,BIOSMSG JMP GO$ON$4 ; BDOS$4: LXI D,BDOSMSG GO$ON$4: CALL PMSG CALL CRLF LXI D,SMSG ;STARTING ADDR MSG CALL PMSG ;PRINT IT LOWER0: ;GET STARTING ADDRESS CALL GETADD ;INPUT ADDR FROM CONIN JNC LOWER2 ;NC MEANS ADDR ENTERED LXI H,LASTB ;CY=CR GIVES DEFAULT PUSH H CALL PHL ;PRINT DEFAULT ADDR POP H LOWER2: IF HEATH OR NOCHEK SHLD MEM ! JMP UPPER0 ;NO CHECKING ENDIF XCHG ;ST ADDR TO DE LXI H,LASTB ;TOP OF THIS PROGRAM CALL HILO ;MUST BE BELOW XCHG ;STARTING ADDR SHLD MEM ;SAVE STARTING ADDR JNC UPPER0 ;LOWER ADDR IS OK, GET UPPER LXI D,LOWMSG CALL PMSG ;SAY TOO LOW LXI H,LASTB CALL PHL ;SAY LOWEST OK ADDR JMP LOWER0 UPPER0: ;GET ENDING ADDR LXI D,EMSG ;ENDING ADDR MSG CALL PMSG CALL GETADD ;GET ENDING ADDR FROM KEYBOARD JNC UPPER2 ;NC MEANS ADDR ENTERED LDA BDOS$FLAG ORA A ;BIOS OUTPUT ? JNZ BDOS$2 ;NO LHLD WBOOT+1 LXI D,BI$OFF ;ESTABLISH DEFAULT ADDRESS JMP GO$ON$2 ; BDOS$2: LHLD BDOS+1 ;CY=CR MEANS DEFAULT LXI D,BD$OFF ;ESTABLISH DEFAULT END ADDR GO$ON$2: DAD D ;JUST BELOW BIOS OR BDOS PUSH H CALL PHL ;PRINT DEFAULT ADDR POP H UPPER2: XCHG ;END ADDR TO DE IF HEATH OR NOCHEK JMP UPPERX ;NO CHECKING ENDIF LHLD MEM ;GET START ADDR INX H CALL HILO ;ERROR,END ADDR MUST JNC UPPERX ;BE ABOVE START ADDR LXI D,UPPMSG CALL PMSG JMP UPPER0 ;TRY AGAIN ; UPPERX: XCHG ;END ADDR SHLD ENDADD ;SAVE ENDING ADDR SHLD SEED ;USE AS SEED ALSO LXI D,CTUMSG ;CONTINUE? CALL PMSG WAIT: CALL CSTAT ;WAIT FOR RESPONSE ORA A JZ WAIT RESTART: CALL CSTAT ;SEE IF ABORT CALL CRLF LDA RAND$FLAG ORA A ;DO RANDOM TEST ONLY ? JNZ RTEST ;YES, GO DO RANDOM NUMBERS ; ;******************************************** ; DO FAST COMPLEMENT TEST - ALL MEMORY ;******************************************** ; LXI D,FCTST CALL PMSG ;PRINT FAST COMP TEST IF NOT HEATH LXI H,0 ;START AT 0 ENDIF IF HEATH LXI H,2000H ENDIF LXI D,FCTEST-1 ;AND STOP AT LOOP CALL FCTEST ;DO TEST LHLD MEMTOPL ;NOW TEST XCHG ;TO MEMTOP LXI H,FCLPX ;STARTING HERE CALL FCTEST ; ;******************************************** ; DO BIT STUCK TEST ;******************************************** LXI D,BSTST CALL PMSG ;PRINT TEST MVI B,0FFH ;FF TEST START CALL TESTW ;WRITE TEST BYTE CALL TESTR ;CHECK TEST BYTE MVI B,0 ;ZEROS TEST CALL TESTW ;WRITE TEST BYTE 0 CALL TESTR ;TEST MVI B,0FFH ;BACK HI TEST CALL TESTW ;WRITE TEST BYTE 0FFH CALL TESTR ;TEST ; ;******************************************** ; DO SHORTED BIT TEST ;******************************************** LXI D,SBTST CALL PMSG ;PRINT BIT SHORT TEST MVI A,1 ;ROTATE BIT TEST LOOP2: MOV B,A ;MAKE TEST BYTE CALL ROTTST ;DO TEST JNC LOOP2 ;DONE WITH 8 BITS? ; ;******************************************** ; DO CHECKERBOARD TEST ;******************************************** LXI D,CBTST CALL PMSG ;PRINT CHECKBOARD TEST MVI B,55H CALL CBTEST MVI B,0AAH CALL CBTEST ; ;******************************************** ; DO WALKING BIT TEST ;******************************************** LXI D,WBLTST CALL PMSG ;PRINT WALKING BIT LEFT MVI B,80H WALL: CALL WALKL ;DO TEST, SAVES B MOV A,B RLC ;NEXT SEED BIT MOV B,A CPI 80H ;DONE IF JNZ WALL LXI D,WBRTST CALL PMSG ;PRINT WALKING BIT RIGHT MVI B,1 WALR: CALL WALKR ;DO TEST, SAVES B MOV A,B RRC ;NEXT SEED BIT MOV B,A CPI 1 ;DONE IF JNZ WALR ; ;******************************************** ; DO ADDRESS LINE TEST ;******************************************** LXI D,ALTST CALL PMSG ;PRINT ADDR LINE TEST MVI B,055H ;TEST BYTE CALL ADTEST ;TEST MVI B,0AAH ;TEST BYTE CALL ADTEST ;TEST ; ;******************************************** ; DO RANDOM NUMBER TEST ;******************************************** RTEST: LXI D,RNTST CALL PMSG MVI C,'1' RANDLP: PUSH B CALL RNDW ;DO RANDOM # TEST CALL SPACE POP B CALL CONO INR C MVI A,'9' CMP C JNZ RANDLP ;CONTINUE RANDOM NR TEST ; LXI D,MSGOK ;POINT AT TEST COMPLETE MSG CALL PMSG JMP RESTART ;START TEST AGAIN WITH OLD PARAMETERS ; ;******************************************** ; FINISHED WITH MAIN LOOP ;******************************************** ; ERROR: ;PRINT ERROR LOCATIONS PUSH B PUSH D PUSH H PUSH PSW ;SAVE ALL REGS CALL CRLF LXI D,MSG1 LDA COUNT CPI RETRYS CZ PMSG ;PRINT LABELS CALL PHL ;PRINT HL REG MOV D,B ;GET SHOULD BE DATA CALL CNVT ;PRINT HEX MOV A,B CALL CNVTB POP PSW PUSH PSW MOV D,A ;GET WAS DATA CALL CNVT ;PRINT HEX POP PSW CALL CNVTB LDA COUNT ;GET ERROR COUNT DCR A ;ONE LESS STA COUNT ;PUT BACK COUNT JNZ MORET LXI D,CTUMSG CALL PMSG CALL GETADD ;SEE IF STOP OR CONTINUE MVI A,RETRYS STA COUNT ;RESET COUNT MORET: POP H ;GET ALL REGS BACK POP D ;AND CONTINUE TEST POP B RET ; PHL: ;PRINT HL REGISTER MOV D,H CALL CNVT ;MAKE ADDR OF ERROR ASCII MOV D,L CALL CNVT CALL TAB RET ; PMSG: ;PRINT STRING POINTED BY DE CALL CSTAT ;POSS ABORT AT EVERY PMSG PMSGLP: LDAX D ;GET BYTE TO PRINT ORA A ;END OF TEXT? RZ MOV C,A ;CONVENTION CALL CONO ;GOTO OUTPUT INX D JMP PMSGLP ; FCTEST: ;COMPLEMENT BYTE AND RESTORE MOV A,M ! CMA MOV M,A ;VERY FAST CHANGE MOV B,A ;SAVE COMPLEMENTED BYTE MOV C,M ;SEE WHAT GOT STORED MOV A,B ! CMA ;ORIG BYTE MOV M,A ;ALWAYS RESTORED FCLPX: MOV A,C ! CMP B ;DID IT COMPLEMENT? CNZ ERROR INX H ! CALL HILO JNC FCTEST ;DO MORE RET ;DONE ; LOAD: ;GET ADDRESSES TO TEST CALL CSTAT ;POSS ABORT AT EVERY LOAD LHLD ENDADD ;GET ENDING ADDR XCHG ;INTO DE LHLD MEM ;GET STARTING ADDR RET ; TESTW: ;FILL MEMORY WITH TEST BYTE CALL LOAD WLOOP: MOV M,B ;PUT TEST BYTE IN MEMORY INX H ! CALL HILO JNC WLOOP RET ; TESTR: ;READ AND COMPARE MEMORY TO TEST BYTE LHLD MEM TESTADR: XCHG LHLD ENDADD ;GET STARTING ADDR XCHG RLOOP: MOV A,M ! CMP B ;CHECK BYTE CNZ ERROR INX H ! CALL HILO JNC RLOOP RET ; CBTEST: ;CHECKERBOARD TEST CALL LOAD CBWLP: MOV M,B ;B HAS TEST BYTE INX H ! CALL HILO JC CBR ;TIME TO READ MOV A,B ! CMA ;55H BECOMES 0AAH MOV M,A ;STORE COMPLEMENT INX H ! CALL HILO JNC CBWLP CBR: ;READ AND TEST CHECKERBOARD CALL LOAD CBRLP: MOV A,M ! CMP B ;CHECK BYTE CNZ ERROR INX H ! CALL HILO RC ;DONE MOV A,B ! CMA ! MOV B,A MOV A,M ! CMP B ;CHECK BYTE CNZ ERROR MOV A,B ! CMA ! MOV B,A INX H ! CALL HILO JNC CBRLP RET ; CSTAT: ;CONSOLE ABORT (SAVES ALL REGS) PUSH H ! PUSH D ! PUSH B CALL JCONS ;SEE IF KEY STRUCK ORA A ;SET FLAGS JZ NOKEY CALL JCONI ;GET KEY CPI ' ' ;EXIT IF SPACE JZ RETURN CPI 3 ;OR ^C JZ RETURN CPI 18H ;^X JZ START ;RE-START TEST NOKEY: POP B ! POP D ! POP H RET ; CNVT: ;CONVERT REG D TO HEX ASCII MOV A,D RRC ;GET HIGH NIBBLE RRC RRC RRC ANI 00FH CALL CNV ;MAKE NIBBLE ASCII MVI A,00FH ANA D ;GET LOW NIBBLE CALL CNV ;MAKE NIBBLE ASCII RET ; CNV: ADI 030H CPI 03AH JM DONE ADI 007H DONE: MOV C,A CALL CONO RET ; ROTTST: ;ROTATE TEST PUSH PSW CALL TESTW POP PSW PUSH PSW CALL TESTR POP PSW RLC RET ; WALKL: ;LEFT WALKING BIT TEST PUSH B ;SAVE SEED CALL LOAD WLSTOR: MOV A,B ;GET BYTE RLC ;ROTATE LEFT MOV B,A ;AND RESAVE IN B MOV M,A ;TO MEMORY INX H ! CALL HILO JNC WLSTOR CALL LOAD POP B ! PUSH B ;GET SEED BIT WLTST: MOV A,B ;NOW CHECK RLC MOV B,A MOV A,M ! CMP B ;CHECK BYTE CNZ ERROR INX H ! CALL HILO JNC WLTST POP B ;ORIG SEED RET ;DONE ; WALKR: ;RIGHT WALKING BIT TEST PUSH B ;SAVE SEED CALL LOAD WRSTOR: MOV A,B ;GET BYTE RRC ;ROTATE RIGHT MOV B,A ;AND RESAVE IN B MOV M,A ;TO MEMORY INX H ! CALL HILO JNC WRSTOR CALL LOAD POP B ! PUSH B ;GET SEED BIT WRTST: MOV A,B ;NOW CHECK RRC MOV B,A MOV A,M ;CHECK BYTE CMP B CNZ ERROR INX H ! CALL HILO JNC WRTST POP B ;ORIG SEED RET ;DONE ; ADTEST: ;ADDRESS SHORTED TEST CALL TESTW ;FILL MEMORY WITH TEST BYTE MOV A,B STA TESTBYTE ;SAVE TEST BYTE CALL LOAD CMA MOV M,A INX H CALL TESTADR LXI B,1 ;START ADDR LSB ON LOOP4: LHLD MEM DAD B RC ;ROLLED OVER 65K MOV A,D ;GET TEST ADDR SUB H ;PAST END? RC ;KEEP GOING IF NO CARRY JNZ INXHA MOV A,E SUB L RC INXHA: LDA TESTBYTE PUSH B MOV B,A CMA ;INVERT BITS MOV M,A ;WRITE TO TEST MEMORY INX H ! CALL HILO JC OVERFL CALL TESTADR ;TEST POP H DAD H RC MOV B,H MOV C,L JMP LOOP4 ; OVERFL: POP B RET ; GETBYT: CALL CHAR RZ CPI ' ' ;EXIT IF SPACE JZ RETURN CPI 3 ;^C JZ RETURN CPI 18H ;^X JZ START CALL ATOH JP REENTER RRC RRC RRC RRC MOV E,A PUSH D CALL CHAR POP D JZ REENTER CALL ATOH JP REENTER ORA E RET ; CHAR: CALL JCONI CPI CR STC ;SET CY FLAG (MAYBE CR) RZ PUSH PSW MOV C,A CALL CONO POP PSW RET ; ATOH: SUI 030H JM BAD CPI 00AH RM SUI 007H CPI 00AH JM BAD CPI 010H RM BAD: XRA A ;SET ZERO FLAG RET ; REENTER: POP H ;FIX STACK LXI D,IEMSG CALL PMSG GETADD: ;INPUT 4 HEX VALUES FROM CONSOLE CALL GETBYT RC MOV H,A SHLD TEMP CALL GETBYT LHLD TEMP MOV L,A RET ; CNVTB: ;PRINT REG A IN BINAR MOV E,A ;SAVE A MVI D,2 ;TWO SPACES CALL TLOP MVI B,2 ;NIBBLE COUNT PNIBB: MVI D,4 ALLBIT: MOV A,E ;RESTORE A RAL MOV E,A MVI C,030H ;0 JNC ZERO MVI C,031H ;1 ZERO: CALL CONO DCR D JNZ ALLBIT CALL SPACE ;PRINT SPACE DCR B JNZ PNIBB TAB: MVI D,004H TLOP: CALL SPACE DCR D JNZ TLOP RET ; CRLF: MVI C,CR ! CALL CONO MVI C,LF ! JMP CONO ; SPACE: MVI C,020H CONO: PUSH B ! PUSH D ! PUSH H LDA BDOS$FLAG ORA A ;BIOS OUTPUT ? JNZ BDOS$3 ;NO CALL JCONO ;YES JMP GO$ON$3 ; BDOS$3: MOV E,C MVI C,2 CALL BDOS GO$ON$3: POP H ! POP D ! POP B RET ; ;RANGE TESTING ROUTINE - CY SET IF RANGE EXCEEDED ; IF HL=DE THEN NC AND Z SET ; IF HL<=DE THEN NC ; IF HL>DE THEN CY AND NZ ; IF HL=0 THEN CY AND Z SET HILOX: INX H ;INCREMENT PNTR, CHECK RANGE HILO: MOV A,H ! ORA L STC ! RZ ;TEST HL=0 MOV A,E ! SUB L ;DE-HL MOV A,D ! SBB H RET ; RNDW: ;WRITE RANDOM NUMBERS LHLD SEED ;GET SEED SHLD SEEDST ;SAVE IT FOR LATER CALL LOAD RNDWL: CALL RND MOV M,B INX H ! CALL HILO JNC RNDWL ; RNDR: ;CHECK AND READ RANDOM NUMBERS LHLD SEEDST ;START WITH SAME SEED SHLD SEED ;PASS SEED TO GENERATOR CALL LOAD ;GET TEST ADDR RNDRL: CALL RND MOV A,M CMP B CNZ ERROR INX H ! CALL HILO JNC RNDRL RET ;TEST DONE ; RND: ;GENERATE RANDOM NR FROM SEED PUSH H LHLD SEED MOV A,L XRA H MOV B,A RLC MOV L,A ADD H MOV H,A SHLD SEED POP H RET ; RETURN: LXI SP,STACK-16 ;FIX STACK JMP JEXIT ; MEMTOP: ;FIND TOP OF MEMORY IF NOT HEATH LXI H,100H-1 ENDIF IF HEATH LXI H,2000H-1 ENDIF MEMLOOP: INR H JZ FOUND ;ABOVE 64K BOUNDRY MOV B,M ;GET MEMORY BYTE MOV A,M ;AND IN A CMA MOV M,A ;STORE COMP MOV C,M ;GET BACK COMP BYTE CMP C ;DID IT STORE OK? MOV M,B ;PUT BACK ORIG JZ MEMLOOP FOUND: DCR H ;FOUND IT RET ;HL=MEMTOP ; ;******************************************** ; MESSAGE AREA ;******************************************** SIG: DB CR,LF DB 'MEMRS Memory Test - Version ' DB VERS/10+30H, '.', VERS MOD 10+30H DB 0 BIOSMSG:DB 'BIOS',0 BDOSMSG:DB 'BDOS',0 LOCMSG: DB ' located at ',0 MEMSG: DB ' Top of memory at ',0 SPMSG: DB CR,LF DB 'Press "SP" or "^C" to warm boot at any time' DB CR,LF DB 'or "^X" to restart test from beginning. ',0 XPMSG: DB CR,LF DB 'Response of "CR" gives default test range' DB CR,LF DB 'which starts above this program and ends at ',0 MSG1: DB 'LOCATION SHOULD BE WAS' DB CR,LF,0 CTUMSG: DB CR,LF DB '"CR" to continue test - "SP", "^C" to quit,' DB ' "^X" to restart.',0 MSGOK: DB CR,LF DB 'Test series complete', 0 SMSG: DB CR,LF DB 'Starting address (Hex or "CR") ',0 EMSG: DB CR,LF DB 'Ending address (Hex or "CR") ',0 IEMSG: DB CR,LF DB 'Input error - Retype 4 hex digits ',0 FCTST: DB CR,LF DB 'Non-destructive test of ALL MEMORY starting at ' IF NOT HEATH DB '0 ',0 ENDIF IF HEATH DB '2000H ',0 ENDIF BSTST: DB CR,LF DB 'Bit stuck high or low test ',0 SBTST: DB CR,LF DB 'Adjacent bits shorted test ',0 CBTST: DB CR,LF DB 'Checkerboard (55AAH pattern) test ',0 WBLTST: DB CR,LF DB 'Walking bit left test ',0 WBRTST: DB CR,LF DB 'Walking bit right test ',0 ALTST: DB CR,LF DB 'Address line test ',0 RNTST: DB CR,LF DB 'Random number test - Cycle: ',0 LOWMSG: DB CR,LF DB 'Re-enter, starting address must be at least ',0 UPPMSG: DB CR,LF DB 'Re-enter, ending address too low',0 ; ; ;******************************************** ; INSERT CUSTOM INITIALIZATION AND I/O ROUTINES HERE ;******************************************** ; IF CPMIO ;THESE ROUTINES CP/M USERS MONIT EQU WBOOT CONST EQU 6 ;CONSOLE STATUS TO REG A CONIN EQU 9 ;CONSOLE CHAR TO REG A CONOUT EQU 0CH ;CHAR FROM REG C TO CONSOLE ; INIT: ;SET HI ORDER ADDR BYTES LDA WBOOT+2 STA JCONS+2 STA JCONI+2 STA JCONO+2 JMP INIT1 ENDIF ; IF LAPIO ;USES LAPPLE MONITOR MONIT EQU 0D000H CONST EQU 0D012H CONIN EQU 0D003H CONOUT EQU 0D009H INIT: JMP INIT1 ;NO INIT NEEDED ENDIF ; IF H84CRT MONIT EQU WBOOT INIT: JMP INIT1 CONST EQU $ CRTST: IN H84ST ! ANI 1 MVI A,0 ! RZ ! CMA ! RET CONIN EQU $ CRTIN: IN H84ST ! RAR ! JNC CRTIN IN H84IO ! ANI 7FH ! RET CONOUT EQU $ CRTOUT: IN H84ST ! ANI 20H ! JZ CRTOUT MOV A,C ! OUT H84IO ! RET H84ST EQU 0EDH H84IO EQU 0E8H ENDIF ; INIT1: LXI H,TBUF ;POINT TO COMMAND LINE MOV A,M ;GET FIRST BYTE CPI '-' ;OPTION CHARACTER ? JNZ DEFAULT ;NO CLOOP: INX H ;POINT TO NEXT BYTE MOV A,M CPI 00 ;END OF COMMAND LINE ? RZ ;YES CPI 'B' ;BDOS OUTPUT ? CZ SET$BDOS ;YES CPI 'R' ;RANDOM TEST ONLY ? CZ SET$RAND ;YES JMP CLOOP ;NO ; DEFAULT: XRA A STA BDOS$FLAG ;BIOS OUTPUT STA RAND$FLAG ;FULL TEST RET ; SET$BDOS: MVI A,TRUE ;BDOS OUTPUT STA BDOS$FLAG RET ; SET$RAND: MVI A,TRUE ;RANDOM NUMBER TEST ONLY STA RAND$FLAG RET ; ;******************************************** ; BDOS$FLAG DB 0 ;BDOS OUTPUT FLAG RAND$FLAG DB 0 ;RANDOM TEST FLAG ; LASTB EQU $ ;END OF PROGRAM ; END START