;******************************************************************* ; ; MNEMONIC - A MULTI-PASS MEMORY TESTER FOR CP/M ; ; COPYRIGHT 1978, BY ; WILLIAM T. PRECHT & ASSOCIATES ; 1102 S. EDSON ; LOMBARD, IL 60148 ; ;******************************************************************** ;MODIFIED 1/11/81 BY CHARLES H. STROM FOR OPERATION WITH MEMORY- ;MAPPED CONSOLE I/O AND WITHOUT A FRONT PANEL. SEE CONDITIONAL ;SWITCHES BELOW. ;******************************************************************** ; ORG 100H ; ORG FOR CP/M TPA ; ; USER MODIFIABLE EQUATES FOLLOW ; MEMMAP EQU 0 ;TRUE FOR MEMORY-MAPPED CONSOLE PANEL EQU 1 ;TRUE FOR FRONT PANEL ; EXITA EQU 0F800H ; COLD BOOT ADDR CONSD EQU 04H ; CONSOLE DATA PORT OR MEMORY LOCATION CONST EQU 05H ; CONSOLE STATUS PORT OR MEMORY LOCATION CONSI EQU 02H ; READY BIT FOR KYBD (ACTIVE HIGH) CONSO EQU 01H ; READY BIT FOR CONSOLE OUTPUT (ACTIVE HIGH) SSWD EQU 20H ; SENSE SW 5 = DETAIL ERROR LIST SSWS EQU 10H ; S.S. 4 = DO SLOW TEST ; ;END OF USER MODIFIABLE EQUATES ; STAK EQU 1000H ; STACK ADDR - PRESERVE THIS STAKH EQU 10H ; STACK H/O ADDR - USED TO COMPARE TO PARMS ; ;******************************************************************* ; JMP START ; BYPASS JUMP TABLE ; EXIT JMP EXITA ; EXIT JUMP - GO TO COLD BOOT ADDR KEYIN JMP ZKEYIN ; CUSTOM CONSOLE INPUT KSTAT JMP ZKSTAT ; " " READY TEST TYPE JMP ZTYPE ; " " OUTPUT ; ;******************************************************************** ; ; CONSOLE KEYBOARD INPUT ROUTINE ; ;******************************************************************** ; ZKEYIN EQU $ CALL KSTAT ; TEST CHAR READY JNC KEYIN ; NOT READY, LOOP IF MEMMAP LDA CONSD ENDIF IF NOT MEMMAP IN CONSD ; READ CONSOLE DATA ENDIF ANI 7FH ; STRIP PARITY CALL TYPE ; ECHO IT TO TERMINAL IF NOT PANEL CPI 'S' ;S FOR SLOW/FAST TOGGLE JNZ XCOMP LDA SLOWTOGL XRI 1 STA SLOWTOGL RET XCOMP CPI 'X' ;X FOR DETAILED/NORMAL LIST TOGGLE RNZ LDA XAMTOGL XRI 1 STA XAMTOGL RET ENDIF RET ; ZKSTAT EQU $ IF MEMMAP LDA CONST ENDIF IF NOT MEMMAP IN CONST ; READ CONSOLE STATUS PORT ENDIF ANI CONSI ; TEST INPUT READY BIT RZ ; NOPE, RET STC ; YUP, SET CARRY RET ; ;******************************************************************** ; ; CONSOLE OUTPUT ROUTINE ; ;******************************************************************** ; ZTYPE EQU $ CALL TYPEC ; TYPE CHAR CPI 0DH ; Q. CARR RTN? RNZ ; NO, RETURN MVI A,0AH ; GET LINE FEED CALL TYPEC ; SEND IT RET ; TYPEC EQU $ PUSH PSW ; SAVE CHAR 2B TYPED TYPEL IF MEMMAP LDA CONST ENDIF IF NOT MEMMAP IN CONST ; READ CONSOLE STATUS ENDIF ANI CONSO ; TEST OUTPUT READY BIT JZ TYPEL ; NOPE, LOOP POP PSW ; ELSE, GET CHAR IF MEMMAP STA CONSD ENDIF IF NOT MEMMAP OUT CONSD ; TYPE IT ENDIF RET ; ; ;******************************************************************* ; ; START - PROGRAM BEGINS; DO INIT ; ;******************************************************************* ; START EQU $ LXI SP,STAK ; GET STACK ADDR CALL PMSG1 ; TYPE VERSION MSG JMP SPARM ; BYPASS CONTINUOUS TEST 1ST TIME ; ;******************************************************************* ; ; MAIN PROGRAM LOOP ; ;******************************************************************** ; LOOP EQU $ CALL KSTAT ; TEST CONSOLE READY JNC CONTIN ; NO, LOOP TILL INTERRUPTED IF MEMMAP LDA CONSD ENDIF IF NOT MEMMAP IN CONSD ; CLEAR INTERRUPTING DATA ENDIF SPARM EQU $ CALL GPARM ; GET ADDRS TO TEST JC SPARM ; LET'S TRY GETTING THOSE PARMS AGAIN CALL QUICK ; DO QUICK TEST FOR MEM PRESENT CONTIN EQU $ CALL RANDS ; SAVE RANDOM SEED CALL GPATT ; GEN RANDOM PATTERNS IN EACH LOC CALL KSTAT ; TEST KYBD READY JC LOOPP ; YES, PRINT MATRIX AND EXIT CALL RANDR ; RESET RAND TO SEED CALL TPATT ; TEST PATTERNS CALL KSTAT ; TEST KYBD READY JC LOOPP ; YES, PRINT MATRIX AND EXIT CALL SLOW ; DO SUPER-SLOW MEM TEST CALL KSTAT ; TEST KYBD READY JC LOOPP ; YES, PRINT MATRIX AND EXIT LHLD PASSC ; GET 16-BIT PASS COUNTER INX H ; PLUS 1 SHLD PASSC ; AND STORE IT BACK CALL PRTPASS ; PRINT PASS COUNT JMP LOOPX ; ELSE, GO TO LOOP EXIT ; LOOPP EQU $ CALL PRMAT ; PRINT ERROR MATRIX ; LOOPX EQU $ JMP LOOP ; LOOP TILL INTERRUPTED ; ; ;******************************************************************** ; ; GPARM - GET ADDRESS PARAMETERS ; ;******************************************************************** ; GPARM EQU $ CALL INIT ; INIT ERROR MATRIX CALL GTSTA ; GET START ADDR RC ; CARRY=ERROR, SO RETURN CALL GTEND ; GET END ADDR RC ; CARRY, PROBLEM RET ; ;******************************************************************** ; ; GPATT - GET RANDOM PATTERN TO ADDRESS SPACE ; ;******************************************************************** ; GPATT EQU $ LHLD AEND ; GET END ADDR TO H-L XCHG ; SWAP IT TO D-E LHLD ASTRT ; GET STARTING ADDR TO H-L GPAT2 EQU $ CALL KSTAT ; TEST KYBD READY RC ; YUP, EXIT CALL RANDB ; GET RANDOM BYTE CALL STNDX ; STORE CHAR, BUMP INDEX JC GPAT2 ; LT MAX, LOOP RET ; ;******************************************************************** ; ; TPATT - TEST RANDOM PATTERN PREVIOUSLY GENERATED ; ;******************************************************************** ; TPATT EQU $ LHLD AEND ; GET END ADDR TO H-L XCHG ; SWAP IT TO D-E LHLD ASTRT ; GET STARTING ADDR TPAT2 EQU $ CALL RANDB ; GET RANDOM BYTE MOV B,M ; GET CHAR FROM MEM TO B CMP B ; TEST EXPECTED TO ACTUAL JZ TPAT3 ; EQ, ON CALL TYPEA ; RECORD ADDR AND FAILURE CALL STMAT ; AND STORE IN ERROR MATRIX ; TPAT3 EQU $ CALL KSTAT ; TEST KYBD STATUS RC ; YES, EARLY EXIT CALL INDEX ; BUMP MEM PTR JC TPAT2 ; LT MAX, LOOP RET ; ;******************************************************************** ; ; STNDX - STORE BYTE IN MEMORY, BUMP INDEX ; ;******************************************************************** ; STNDX EQU $ MOV M,A ; STORE CHAR IN MEM JMP INDEX ; BUMP MEM PTR AND EXIT ; ;******************************************************************** ; ; INDEX - BUMP H-L, COMPARE TO D-E (ENDING ADDR) ; ;******************************************************************** ; INDEX EQU $ MOV A,H ; GET H/O OF CURR ADDR CMP D ; TEST TO H/O OF END JC INXIT ; LT, ONWARD JNZ INXIT ; NOT ZERO, END MOV A,L ; TEST L/O CMP E ; TO L/O OF END JC INXIT ; LT, ON ; ; H-L = D-E ; RESET ZERO AND CARRY FLAGS ; MVI A,0 ; GET ZERO DCR A ; RESET ZERO FLAG ORA A ; AND CARRY RET ; INXIT EQU $ INX H ; BUMP MEM PTR RET ; ;******************************************************************** ; ; STMAT - STORE BIT DIFFERENCES IN ERROR MATRIX ; ;******************************************************************** ; STMAT EQU $ PUSH PSW ; SAVE CHAR PUSH H ; SAVE H-L PUSH D ; AND PUSH B ; REST MOV B,A ; MOVE BYTE READ TO B MOV C,M ; MOVE BYTE WRITTEN TO C MOV A,H ; GET H/O ERROR ADDR PUSH PSW ; SAVE H/O LHLD ASTRT ; STARTING TEST ADDR MOV A,H ; GET H/O TO ACC ANI 0FCH ; STRIP L/O 2 BITS MOV H,A ; REPLACE H/O POP PSW ; RESTORE H/O ERR ADDR SUB H ; 256-BYTE DIFF ANI 0FCH ; CLEAR L/O 2 BITS MVI H,0 ; SETUP H-L MOV L,A ; TO FORM DAD H ; K INDEX TO MATRIX DAD H ; AGAIN LXI D,MATRX ; MATRIX START DAD D ; FORM K INDEX SHLD MINDX ; STORE MATRIX INDEX LHLD ERRCT ; GET ERROR COUNT INX H ; PLUS 1 SHLD ERRCT ; AND STORE IT BACK LXI D,8 ; BIT COUNT TO D STMA2 EQU $ MOV A,B ; GET BYTE READ RRC ; SHIFT L/O INTO CARRY MOV B,A ; RETURN BYTE READ MOV A,C ; GET BYTE WRITTEN JC STMC1 ; BIT WAS SET IN READ - SEE IF WRITTEN RRC ; SHIFT BYTE WRITTEN L/O BIT INTO CARRY MOV C,A ; RETURN BYTE WRITTEN JNC STMCO ; NOT CARRY, BIT MATCHES JMP STMBT ; CARRY, FLAG ERR STMC1 EQU $ RRC ; SHIFT WRITTEN BIT INTO CARRY MOV C,A ; RETURN BYTE WRITTEN JC STMCO ; CARRY, BIT MATCHES STMBT EQU $ PUSH D ; SAVE ERR CTR MVI H,0 ; SETUP MOV L,E ; H-L DCR L ; TAKE BIT COUNT - 1 DAD H ; * 2 XCHG ; SWAP TO D-E LHLD MINDX ; MATRIX K INDEX DAD D ; DISPLACE BIT LOC MOV E,M ; GET L/O OF ERROR CTR INX H ; BUMP PTR MOV D,M ; GET H/O INX D ; INCR DBL CTR MOV M,D ; REPLACE H/O DCX H ; DECR MEM PTR MOV M,E ; REPLACE L/O POP D ; RESTORE D-E ; STMCO EQU $ DCR E ; MINUS BIT COUNTER JNZ STMA2 ; LOOP TILL ALL BITS TESTED POP B ; RESTORE POP D ; ALL POP H ; REGS POP PSW ; AND CHAR RET ; ;******************************************************************** ; ; PMSG1 - TYPE VERSION MESSAGE AND INSTRUCTIONS ; ;******************************************************************** ; PMSG1 EQU $ LXI H,MSG1 ; GET VERSION MESSAGE CALL LINE ; TYPE LINE RET ; MSG1 DB 0DH DB 'WTP&A MNEMONIC - VERSION 2.1',0DH DB 0DH DB 'ANY MEMORY FROM 1000H TO FFFFH CAN BE TESTED.',0DH DB 'TEST WILL RUN CONTINUOUSLY ' DB 'UNTIL A KEY IS STRUCK.',0DH IF PANEL DB 'TURN ON S.S. 5 TO GET DETAILED ERROR LIST;',0DH DB ' S.S. 4 TO DO SUPER-SLOW TEST.',0DH ENDIF IF NOT PANEL DB 'AT "START ADDRESS" PROMPT ENTER;',0DH DB 'S - To toggle test SPEED normal/super slow;',0DH DB 'X - To toggle normal/detailed EXAMINATION of errors' ENDIF DB 0DH,0DH DB 'WHEN A KEY IS STRUCK, ALL CUMULATIVE ERRORS',0DH DB ' WILL BE SUMMARIZED BY BIT POSITION',0DH DB ' WITHIN 1K BOUNDARIES.',0DH DB 0DH DB '(ALL INPUTS AND OUTPUTS ARE IN HEX.)',0DH DB 0DH DB 00 ; ;******************************************************************** ; ; PMSGS - PRINT STARTING ADDR REQ MSG ; ;******************************************************************** ; PMSGS EQU $ LXI H,MSGS ; GET START ADDR REQ MSG CALL LINE ; TYPE LINE RET ; MSGS DB 'START ADDR (HEX) ?',0DH,00 ; ;******************************************************************** ; ; PMSGE - TYPE ENDING ADDR REQ MSG ; ;******************************************************************** ; PMSGE EQU $ LXI H,MSGE ; GET ENDING ADDR REQ MSG CALL LINE ; TYPE LINE RET ; MSGE DB 'END ADDR (HEX) ?',0DH,00 ; ;******************************************************************** ; ; LINE - TYPE A LINE TERMINATED BY X'00' ; ;******************************************************************** ; LINE EQU $ MOV A,M ; GET CHAR FROM MSG CPI 00 ; Q. MSG END? JZ LINEX ; YUP, WRAP UP CALL TYPE ; ELSE, TYPE CHAR INX H ; BUMP PTR JMP LINE ; LOOP TILL MSG END ; LINEX EQU $ RET ; ;******************************************************************** ; ; GTSTA - GET MEMORY STARTING ADDRESS ; ;******************************************************************** ; GTSTA EQU $ CALL PMSGS ; SEND STARTING REQ MSG CALL RDADR ; READ ADDR FROM CONSOLE JC GTSTA ; CARRY=ERROR, SO REPROMPT CALL PACKA ; PACK ADDR INTO ADDRH LHLD ADDRH ; GET PACKED ADDR SHLD ASTRT ; SAVE IT IN STARTING ADDR MOV A,H ; GET H/O OF START ADDR CPI STAKH ; TEST TO STACK ADDR RET ; ;******************************************************************** ; ; GTEND - GET ENDING ADDRESS ; ;******************************************************************** ; GTEND EQU $ CALL PMSGE ; SEND ENDING REQ MSG CALL RDADR ; READ ADDR FROM CONSOLE JC GTEND ; CARRY=ERROR, SO REPROMPT CALL PACKA ; PACK ADDR INTO ADDRH LHLD ADDRH ; GET PACKED ADDR SHLD AEND ; SAVE IT IN ENDING ADDR XCHG ; SWAP TO D-E LHLD ASTRT ; GET STARTING ADDR TO H-L MOV A,D ; GET H/O OF ENDING ADDR CMP H ; TEST TO H/O OF START RC ; LT, ERROR RNZ ; NOT ZERO, GO ON MOV A,E ; GET L/O OF END CMP L ; TEST TO L/O OF START RC ; LT, ERROR ORA A ; CLEAR CARRY RET ; ;******************************************************************** ; ; RDADR - READ 4-BYTE ADDRESS FROM CONSOLE, ; CONVERT IT TO HEX AND STORE IT. ; ;******************************************************************** ; RDADR EQU $ LXI H,NRAND ; RANDOMLY CREATE NRAND LXI D,ADDRA ; ADDR TO FILL MVI B,4 ; CHAR COUNT ; RDSTA EQU $ CALL KSTAT ; TEST KYBD STATUS JC RDBYT ; CARRY= CHAR READY INR M ; ELSE, ADD TO NRAND DIGIT JMP RDSTA ; LOOP TILL CHAR ; RDBYT EQU $ CALL KEYIN ; READ CHAR CALL TESTK ; TEST VALIDITY JC RDERR ; NG, RESTART STAX D ; OK, STORE CHAR INX D ; BUMP ADDRA PTR INX H ; AND NRAND PTR DCR B ; MINUS LTH COUNTER JNZ RDSTA ; LOOP TILL DONE MVI A,0DH ; CARR RTN CALL TYPE ; TYPE IT RET ; RDERR EQU $ PUSH H ; SAVE H-L (NRAND DIGIT) LXI H,MSGKE ; GET ERR MSG ADDR CALL LINE ; TYPE LINE POP H ; RESTORE H-L STC ; SHOW ERROR RET ; MSGKE DB 0DH IF PANEL DB 'YOU WANTA TRY THAT AGAIN?',0DH ENDIF DB 00 ; ;******************************************************************** ; ; TESTK - TEST KEYIN CHARACTER. ; IF CTL-C, DO COLD BOOT ; ;******************************************************************** ; TESTK EQU $ CPI 03H ; CTL-C? JZ EXIT ; YUP, GET OUT CPI '0' ; NUMERIC JC TSKNG ; NOPE, ERR CPI '9'+1 ; REALLY NUMERIC? JNC TSKAF ; NO, TEST A-F SUI 30H ; ADJUST TO BINARY ORA A ; RESET CARRY RET ; TSKAF EQU $ CPI 'A' ; TEST "A" JC TSKNG ; LT, ERR CPI 'F'+1 ; TEST "F" JNC TSKNG ; GT F, ERR SUI 37H ; SUBTRACT 55 ORA A ; RESET CARRY RET ; TSKNG EQU $ STC RET ; ;******************************************************************** ; ; PACKA - PACK ADDRESS KEYED-IN ; ;******************************************************************** ; PACKA EQU $ LXI H,ADDRA ; GET PARTIALLY-CONVERTED ADDR CALL PACKB ; PACK A BYTE MOV D,A ; PUT IT OVER THERE FOR THE NONCE CALL PACKB ; PACK 2ND BYTE MOV E,A ; COMBINE XCHG ; THEM INTO H-L SHLD ADDRH ; SAVE THEM IN ADDRH RET ; PACKB EQU $ MOV A,M ; GET CHAR FROM INPUT RLC ; ROTATE RLC ; IT RLC ; TO RLC ; H/O ANI 0F0H ; CLEAR L/O MOV B,A ; SAVE IT IN B INX H ; BUMP MEM PTR MOV A,M ; GET NEXT CHAR ORA B ; OR ON H/O FROM B INX H ; BUMP MEM PTR AGAIN RET ; ;******************************************************************** ; ; RANDS - SAVE RANDOM NUMBER FOR LATER RESTORATION ; ;******************************************************************** ; RANDS EQU $ LXI H,NRAND+3 ; PT TO L/O OF 4-BYTE RANDOM NUMBER MVI A,01 ; ENSURE ORA M ; THAT L/O OF NRAND MOV M,A ; ENDS IN 1 LXI D,NRNDS+3 ; POINT D TO RAND SAVE JMP RNDS2 ; GO TO COMMON MOVE RTN ; RANDR EQU $ LXI H,NRNDS+3 ; FROM ADDR = RAND SAVE LXI D,NRAND+3 ; TO ADDR = RANDOM NUMBER ; RNDS2 EQU $ MVI B,4 ; COUNT = 4 ; RNDSL EQU $ MOV A,M ; GET CHAR FROM SOURCE STAX D ; COPY IT TO DEST DCX D ; DECR DCX H ; BOTH PTRS DCR B ; MINUS COUNT JNZ RNDSL ; LOOP TILL DONE RET ; ; ;******************************************************************** ; ; DATA AREAS ; ;******************************************************************** ; NRAND DS 4 ; PSEUDO-RANDOM NUMBER NRNDS DS 4 ; RAND SAVE AREA ; MLTPR DW 0A5A5H ; RANDOM MULTIPLIER ; PRDAD DW 0 ; PARTIAL PRODUCT A*D PRDBD DW 0 ; " " B*D PRDBC DW 0 ; " " B*C ; ADDRA DS 4 ; ADDR INPUT ADDRH DS 2 ; HEX EQUIV. OF ADDRA ; ASTRT DS 2 ; HEX STARTING ADDR AEND DS 2 ; HEX ENDING ADDR ATEST DS 2 ; HEX TEST ADDR FOR "SLOW" ; MINDX DW 0 ; K INDEX TO ERROR MATRIX ; PASSC DW 0 ; PASS COUNTER ERRCT DW 0 ; ERROR COUNTER ; DS 2 MATRX DS 1024 ; ERROR MATRIX (64K * 16) DS 2 SLOWTOGL DB 0 ;SLOW TEST TOGGLE XAMTOGL DB 0 ;DETAILED LIST TOGGLE ; ; ;******************************************************************** ; ; GENERATE RANDOM BYTE ; ;******************************************************************** ; RANDB EQU $ PUSH D ; SAVE PUSH H ; REGS LDA MLTPR+1 ; GET MULTIPLIER L/O MOV C,A ; SAVE IN C LDA NRAND+3 ; GET NRAND L/O MOV B,A ; SAVE IN B CALL MULT ; GET 16-BIT PRODUCT IN H-L SHLD PRDBD ; STORE 1ST PARTIAL PRODUCT LDA MLTPR+1 ; GET MULTIPLIER H/O MOV C,A ; SAVE IN C LDA NRAND+2 ; GET NRAND DIG MOV B,A ; SAVE IN B CALL MULT ; DO MULTIPLICATION SHLD PRDBC ; SAVE PARTIAL PRODUCT LDA MLTPR ; GET MULTIPLIER L/O MOV C,A ; SAVE IN C LDA NRAND+3 ; GET NRAND L/O MOV B,A ; SAVE IN B CALL MULT ; DO MULTIPLICATION SHLD PRDAD ; SAVE 3RD PARTIAL PROD LDA PRDBD ; GET NEW L/O DIGIT STA NRAND+3 ; UPDATE NRAND L/O LXI H,0 ; GET CLEAR SUM MVI B,0 ; CLEAR H/O OF ADDEND LDA PRDBD+1 ; GET H/O OF PROD BD MOV C,A ; TO L/O OF ADDEND DAD B ; ADD INTO SUM LDA PRDBC ; GET L/O OF PROD BC MOV C,A ; TO L/O OF ADDEND DAD B ; ADD INTO SUM LDA PRDAD ; GET L/O OF PROD AD MOV C,A ; TO L/O OF ADDEND DAD B ; ADD INTO SUM MOV A,L ; GET L/O OF SUM STA NRAND+2 ; UPDATE NRAND TO NEW VALUE POP H ; RESTORE POP D ; REGS RET ; ;******************************************************************** ; ; MULT B * C = PROD IN H-L ; ;******************************************************************** ; MULT EQU $ PUSH D ; SAVE D-E MOV A,B ; COPY MULTIPLICAND TO A MVI B,0 ; CLEAR UPPER ADDEND LXI H,0 ; INIT PRODUCT TO ZERO MVI D,8 ; MULTIPLIER BIT COUNT MULT2 EQU $ DAD H ; SHIFT PRODUCT LEFT RLC ; MULTIPLIER BIT TO CARRY JNC MULTC ; SKIP IF BIT ZERO DAD B ; ELSE, ADD MPCND TO PARTIAL PRODUCT MULTC EQU $ DCR D ; DECR BIT COUNT JNZ MULT2 ; LOOP TILL DONE POP D ; RESTORE D-E RET ; ;******************************************************************** ; ; PRMAT - PRINT ERROR BIT MATRIX ; ;******************************************************************** ; PRMAT EQU $ CALL PRTPASS ; PRINT PASS COUNT LHLD ERRCT ; GET ERROR COUNT MOV A,H ; GET H/O ORA A ; Q. 0? JNZ PRMAH ; NO, GO THRU MATRIX MOV A,L ; GET L/O ORA A ; Q. ZERO? JZ PRMAX ; YES, BYPASS MATRIX SEARCH PRMAH EQU $ LXI H,MSGBH ; GET BIT ERR MSG HEADER CALL LINE ; TYPE IT LHLD ASTRT ; GET STARTING ADDR MOV A,H ; GET H/O ANI 0FCH ; MASK OFF L/O 2 BITS MOV H,A ; AND MOVE IT BACK XCHG ; MOVE TO D-E LXI H,MATRX ; POINT TO ERROR MATRIX MVI B,64 ; COUNT OF K'S TO SEARCH PRMA3 EQU $ MVI C,8 ; # OF BIT COUNTERS PER K PUSH H ; SAVE CURRENT K INDEX TO MATRIX PRMA4 EQU $ MOV A,M ; GET BIT COUNTER ORA A ; Q. ZERO? JNZ PRMA5 ; NO, MUST PRINT THIS K INX H ; ELSE, BUMP TO NEXT BIT CTR MOV A,M ; GET H/O OF BIT CTR ORA A ; TEST ZERO JNZ PRMA5 ; NO, PRINT K INX H ; YES, BUMP MEM PTR DCR C ; MINUS BIT COUNTER JNZ PRMA4 ; NOT DONE TESTING THIS K, LOOP JMP PRMA7 ; ELSE, TRY NEXT K PRMA5 EQU $ POP H ; RESTORE STARTING K INDEX MVI C,8 ; RESTART BIT COUNTER XCHG ; GET CURR K ADDR PUSH H ; SAVE IT MVI L,0 ; PRINT K ADDR ON EVEN BOUNDARY MVI A,' ' ; BLANK FOR SPACING CALL TYPE ; TYPE IT CALL TYPEB ; TYPE IT LXI H,MSG2B ; 2 BLANKS CALL LINE ; TYPE THEM POP H ; RESTORE K ADDR XCHG ; THEN SWAP BACK PRMA6 EQU $ PUSH D ; SAVE TARGET ADDR MOV E,M ; GET 1ST BYTE TO E INX H ; BUMP MEM PTR MOV D,M ; GET 2ND BYTE XCHG ; SWAP TO H-L CALL TYPEB ; TYPE CTR AS THO ADDR XCHG ; SWAP BACK POP D ; RESTORE D-E INX H ; BUMP MEM PTR DCR C ; MINUS COUNT JNZ PRMA6 ; LOOP TILL DONE MVI A,0DH ; CARR RTN CALL TYPE ; TYPE IT JMP PRMA8 ; AND GO TEST NEXT MATRIX LVL ; PRMA7 EQU $ POP H ; RESTORE H-L PUSH B ; SAVE COUNTERS LXI B,16 ; GET OFFSET TO NEXT K DAD B ; BUMP H-L POP B ; RESTORE COUNTERS PRMA8 EQU $ DCR B ; MINUS K COUNTER JZ PRMAX ; ZERO, DONE XCHG ; GET START ADDR PUSH B ; SAVE BIT COUNTERS LXI B,400H ; GET K BOUNDARY DAD B ; ADJUST START ADDR XCHG ; SWAP BACK POP B ; RESTORE BIT COUNTERS JMP PRMA3 ; LOOP TILL DONE ; PRMAX EQU $ RET ; MSGBH DB 'K ADDR B7 B6 B5 B4' DB ' B3 B2 B1 B0' DB 0DH,00 ; ;******************************************************************** ; ; PRTPASS - PRINT PASS COUNTER AND TOTAL ERRORS ; ;******************************************************************** ; PRTPASS EQU $ LXI H,MSGPC ; GET PASS COUNT MSG ADDR CALL LINE ; TYPE IT LHLD PASSC ; GET PASS COUNTER CALL TYPEB ; TYPE IT LXI H,MSGER ; ERROR COUNT MESSAGE CALL LINE ; TYPE LINE LHLD ERRCT ; GET ERROR COUNTER CALL TYPEB ; TYPE COUNT OF ERRORS MVI A,0DH ; CARR RTN CALL TYPE ; END LINE RET ; MSGPC DB 'PASSES COMPLETED = ',00 MSGER DB '; COUNT OF ERROR BYTES = ',00 DB 00 ; ;******************************************************************** ; ; TYPEH - TYPE A BYTE IN 2-DIGIT HEX ; ;******************************************************************** ; TYPEH EQU $ PUSH B ; SAVE COUNT MOV B,A ; SAVE CHAR IN B ANI 0F0H ; STRIP L/O RRC ; SHIFT RRC ; TO RRC ; L/O RRC ; 4 BITS CALL TYPHH ; TYPE HEX MOV A,B ; GET CHAR BACK ANI 0FH ; NOW STRIP H/O CALL TYPHH ; TYPE HEX POP B ; RESTORE COUNT RET ; TYPHH EQU $ ADI 90H ; DO DAA ; HEX TO ASCII ACI 40H ; ADJUSTMENT DAA ; TRICK CALL TYPE ; TYPE ADJUSTED HEX CHAR RET ; ;******************************************************************** ; ; QUICK - DO QUICK TEST OF MEMORY RANGE ; USING X'FF' AND X'00' ; ;******************************************************************** ; QUICK EQU $ MVI C,0FFH ; USE FOXES FIRST CALL QTEST ; DO QUICK TEST CALL KSTAT ; TEST KYBD READY RC ; YES, EXIT MVI C,00H ; NOW USE ZEROS CALL QTEST ; DO QUICK TEST AGAIN RET ; QTEST EQU $ LHLD AEND ; GET END ADDR TO H-L XCHG ; SWAP IT TO D-E LHLD ASTRT ; GET STARTING ADDR QTES2 EQU $ CALL KSTAT ; TEST KYBD READY RC ; YES, EXIT MOV A,C ; GET STORING VALUE CALL STNDX ; STORE CHAR IN MEM, BUMP INDEX JC QTES2 ; LT, MORE LHLD ASTRT ; GET START ADDR AGAIN QTES3 EQU $ CALL KSTAT ; TEST KYBD READY RC ; YES, EXIT MOV A,C ; GET STORED VALUE MOV B,M ; GET CHAR FROM MEM CMP B ; TEST EACH DIGIT AGAINST EXPECTED JZ QTES4 ; EQ, ON CALL TYPEA ; ELSE, TYPE ERR VALS CALL STMAT ; STORE BIT ERRORS IN MATRIX QTES4 EQU $ CALL INDEX ; BUMP INDEX JC QTES3 ; LT, AGAIN RET ; ;******************************************************************** ; ; SLOW - DO SUPER-SLOW MEM TEST. ; FIRST, MARCH A 1 BIT THRU A FLD OF ZEROS, ; TESTING EACH OTHER BYTE IN THE RANGE FOR ; A CHANGE. ; THEN, MARCH A ZERO BIT THRU A FLD OF ONES, ; TESTING AS ABOVE. ; ;******************************************************************** ; SLOW EQU $ IF PANEL IN 255 ; READ SENSE SWS ANI SSWS ; TEST SLOW SELECTED ENDIF IF NOT PANEL LDA SLOWTOGL ANI 01 ;DO SLOW TEST IF SLOWTOGL=1 ENDIF RZ MVI B,00 ; ZEROS TO MEM FOR 1ST PHASE CALL SETMEM ; CLEAR ADDR SPACE MVI C,01 ; BIT REG SLOW2 EQU $ CALL SLOWT ; DO SLOW TEST CALL KSTAT ; TEST FOR INTERRUPTION RC ; YES, GO MOV A,C ; GET BIT REG RLC ; SHIFT BIT JC SLOW3 ; WHEN BIT REACHES CARRY, DONE MOV C,A ; REPLACE BIT JMP SLOW2 ; NOT DONE, CONTINUE SLOW3 EQU $ MVI B,0FFH ; ALL ONES CALL SETMEM ; TO ADDR SPACE MVI C,0FEH ; BIT REG TO A L/O ZERO SLOW4 EQU $ CALL SLOWT ; DO SLOW TEST CALL KSTAT ; TEST FOR INTERRUPTION RC ; YES, GO MOV A,C ; GET BIT REG RLC ; SHIFT 0 BIT LEFTWARDS JNC SLOW5 ; WHEN ZERO REACHES CARRY, DONE MOV C,A ; REPLACE BIT REG JMP SLOW4 ; NOT DONE, CONTINUE ; SLOW5 EQU $ MVI B,08 ; COUNT OF BELLS SLOWB EQU $ MVI A,07H ; BELL CHAR CALL TYPE ; SOUND IT CALL KSTAT ; TEST KYBD READY JC SLOWX ; YES, CLEANUP LXI H,0 ; LONG WAIT SLOW6 EQU $ DCR L ; JNZ SLOW6 ; DCR H ; JNZ SLOW6 ; DCR B ; MINUS BELL COUNT JNZ SLOWB ; NOT DONE, RING AGAIN SLOWX EQU $ MVI A,0DH ; CR CALL TYPE ; TYPE IT RET ; SLOWT EQU $ LHLD ASTRT ; GET STARTING ADDR FOR TEST SHLD ATEST ; STORE IT AT TEST ADDR SLOWT2 EQU $ LHLD ATEST ; GET TEST ADDR MOV M,C ; STORE BIT REG AT TEST BYTE LHLD AEND ; ENDING ADDR TO H-L XCHG ; SWAP IT TO D-E LHLD ASTRT ; GET STARTING ADDR SLOWS2 EQU $ MOV A,M ; GET BYTE FROM MEM CMP B ; TEST TO EXPECTED JZ SLOWS5 ; EQ, ON PUSH B ; SAVE B-C MOV C,A ; SAVE CHAR READ (ERROR) XCHG ; CURRENT ADDR TO D-E LHLD ATEST ; GET TEST ADDR TO H-L MOV A,H ; GET H/O ADDR OF TEST BYTE CMP D ; TEST TO D JNZ SLOWS3 ; NOT EQ, ON MOV A,L ; GET L/O CMP E ; TEST L/O OF TEST ADDR JNZ SLOWS3 ; NOT EQUAL, PRT ERROR JMP SLOWS4 ; AND BYPASS ERROR PRT SLOWS3 EQU $ MOV A,B ; SWAP EXPECTED TO ACC MOV B,C ; INSERT VALUE READ IN ERROR CALL TYPEA ; TYPE ADDR CALL STMAT ; STORE IN ERR MATRIX SLOWS4 EQU $ POP B ; RESTORE B-C LHLD AEND ; GET ENDING ADDR XCHG ; CURRENT ADDR BACK TO H-L SLOWS5 EQU $ INX H ; BUMP MEM PTR MOV A,H ; GET H/O OF CURR ADDR CMP D ; TEST TO H/O OF END ADDR JC SLOWS2 ; LT, CONTINUE MOV A,L ; GET L/O OF CURR ADDR CMP E ; TEST TO L/O OF END ADDR JC SLOWS2 ; LT, ON SLOWSX EQU $ CALL KSTAT ; TEST FOR INTERRUPTION RC ; YES, GO LHLD ATEST ; GET TEST ADDR MOV M,B ; REPLACE TEST BYTE INX H ; BUMP TEST ADDR SHLD ATEST ; AND RESAVE IT XCHG ; SWAP TEST ADDR TO D-E LHLD AEND ; GET END ADDR TO H-L MOV A,D ; GET H/O OF TEST ADDR CMP H ; TEST TO H/O OF END ADDR JC SLOWT2 ; LT, ON JNZ SLOWTX ; NOT EQ, DONE MOV A,E ; GET L/O OF TEST ADDR CMP L ; TEST TO L/O OF END ADDR JC SLOWT2 ; LT, ON JZ SLOWT2 ; EQ, 1 MORE TIME SLOWTX EQU $ RET ; ;******************************************************************** ; ; SETMEM - SET ADDR SPACE TO VALUE IN B ; ;******************************************************************** ; SETMEM EQU $ LHLD AEND ; GET ENDING ADDR XCHG ; TO D-E LHLD ASTRT ; GET STARTING ADDR SETM2 EQU $ MOV M,B ; FILL MEM BYTE CALL INDEX ; BUMP PTR JC SETM2 ; LT, LOOP RET ; ;******************************************************************** ; ; INIT - SETUP MATRIX ; ;******************************************************************** ; INIT EQU $ LXI H,MATRX ; GET ERROR MATRIX ADDR LXI B,1024 ; GET MATRIX LENGTH XRA A ; GET ZERO INIT2 EQU $ MOV M,A ; STORE ZERO IN ERROR MATRIX BYTE INX H ; BUMP MEM PTR DCR C ; MINUS L/O OF COUNT JNZ INIT2 ; INNER LOOP DCR B ; MINUS COUNT JNZ INIT2 ; LOOP TILL DONE LXI H,0 ; ZEROS TO SHLD PASSC ; PASS COUNTER SHLD ERRCT ; AND ERROR COUNTER RET ; ;******************************************************************** ; ; TYPEA - TYPE ERROR ADDR, WROTE, READ ; ;******************************************************************** ; TYPEA EQU $ PUSH PSW ; SAVE CHAR 2B TYPED IF PANEL IN 255 ; READ SENSE SWS ANI SSWD ; TEST DETAIL LIST SENSE SW ENDIF IF NOT PANEL LDA XAMTOGL ANI 01 ; DO DETAILED LIST IF XAMTOGL=1 ENDIF JZ TYPAX ; YES, DON'T DETAIL ERRS PUSH H ; SAVE ADDR OF ERROR LHLD ERRCT ; GET ERROR COUNTER MOV A,H ; GET H/O ORA A ; Q. ZERO? JNZ TYPA2 ; NO, ALREADY PRINTED HEADER MOV A,L ; GET L/O ORA A ; Q. ZERO? JNZ TYPA2 ; NO, BYPASS LXI H,MSGEH ; GET ERROR HEADER MSG CALL LINE ; TYPE IT TYPA2 EQU $ POP H ; RESTORE ERROR ADDR CALL TYPEB ; CONVERT AND TYPE H-L PUSH H ; SAVE H-L AGAIN LXI H,MSG2B ; 2 BLANKS CALL LINE ; TYPE IT POP H ; RESTORE H-L POP PSW ; GET CHAR PUSH PSW ; RESAVE IT CALL TYPEH ; TYPE IT PUSH H ; SAVE H-L AGAIN LXI H,MSG3B ; 3 BLANKS CALL LINE ; TYPE IT POP H ; RESTORE H-L MOV A,B ; GET CHAR READ CALL TYPEH ; TYPE IT MVI A,0DH ; CARR RTN CALL TYPE ; SEND IT TYPAX EQU $ POP PSW ; RESTORE CHAR RET ; MSGEH DB 'ADDR WROTE READ',0DH DB 00 MSG3B DB ' ' MSG2B DB ' ',00 ; ;******************************************************************** ; ; TYPEB - TYPE 2-BYTE ADDRESS IN H-L ; ;******************************************************************** ; TYPEB EQU $ MOV A,H ; GET H/O OF ADDR CALL TYPEH ; TYPE IT MOV A,L ; GET L/O CALL TYPEH ; TYPE IT MVI A,' ' ; BLANK CALL TYPE ; FOR SEPARATION RET ; END