;COMPBIN.ASM ;MOD OF COMPARE.ASM FOR BINARY FILES ;INCLUDES REPORTING AND ACCEPTANCE OF INSERTIONS, ;DELETIONS, ETC. ; ;COMPARE.ASM ;11/??/77 ORIGINALLY WRITTEN BY WARD CHRISTENSEN ;12/31/77 ADD PICKUP OF SECOND FILENAME IF BLANK ;01/08/77 ADD SEQIO MACLIB TO READ BIG BLOCKS ;09-09-82 MOD TO COMPBIN BY RUSS BAKKE ; MACLIB SEQIO BSIZE EQU 1024 ;DISK BUFFER SIZE (TIMES 2) ORG 100H ; ;MACRO DEFS PRINT MACRO ?L LOCAL Z CALL Z IRP ?M, DB ?M ENDM DB '$' Z POP D MVI C,@MSG CALL @BDOS ENDM ; GETF MACRO ?B,?P,?F,?E,?L,?N LOCAL Q,R,S IF NOT NUL ?B LXI H,?B ENDIF IF NOT NUL ?P SHLD ?P ENDIF IF NOT NUL ?L LXI B,?L ENDIF Q PUSH B PUSH H CALL ?F POP H POP B MOV M,A JZ R ;EOF INX H DCX B MOV A,B ;DONE? ORA C JNZ Q ;NO JMP S ; R MVI A,1 ;SET EOF FLAG STA ?E ; S SHLD ?N ;SAVE EOF ADDR ENDM ; REFILL MACRO ?B,?P,?E,?C LOCAL P PUSH D SHLD ?C XCHG LXI B,8192 ;BUFFER SIZE LHLD ?P PUSH H MOV A,H ;NEGATE HL CMA MOV H,A MOV A,L CMA MOV L,A INX H DAD D ;ADD DE LXI D,?B DAD D ;ADD BUFST SHLD ?C POP H P MOV A,M ;MOVE CHAR STAX D DCX B ;COUNT IT INX D ;MOVE POINTERS INX H CALL ?E JNZ P ENDM ; CKEOB MACRO ?E PUSH D LXI D,?E CALL CMPHD POP D ENDM ; CKEOF MACRO ?E PUSH D XCHG LHLD ?E XCHG CALL CMPHD POP D ENDM ; ;COMPBIN.ASM - COMPARES 2 BINARY FILES ; ;COMMAND FORMAT: COMPBIN NAME1 NAME2 ; IF NAME2 = NAME1 BUT IS ON B DISK, ; JUST TYPE: COMPBIN NAME1 B: ; LXI SP,STACK ;INIT STACK ; PRINT <'COMPBIN.COM 09-09-82',0DH,0AH> ; ;IF THE SECOND FCB IS BLANK, ;MOVE IN THE NAME FROM THE FIRST ; LDA @TFCB+17 CPI ' ' JNZ MOVE2 ;NOT BLANK MVI B,11 LXI D,@TFCB+1 LXI H,@TFCB+17 CALL MOVER ; ;'DECLARE' BOTH FCB'S ; MOVE2 FILE INFILE,FILE1,,1,,BSIZE FILE INFILE,FILE2,,2,,BSIZE ; ;COMPARE THE 2 FILES ; ;FIRST, READ 8K INTO FIRST BUFFER GETF BUF1ST,OK1,GETFILE1,EOF1FG,8192,EOF1 ;READ 8K INTO SECOND BUFFER GETF BUF2ST,OK2,GETFILE2,EOF2FG,8192,EOF2 ; ;NOW START COMPARE LXI H,BUF1ST LXI D,BUF2ST COMP LDAX D CMP M JNZ DIFFER INX H INX D ;ARE WE AT START OF NEW 8 BYTE BLOCK? ;(IN ORDER TO HANDLE MOVING POINTERS, WE ;KEEP POINTERS TO KNOWN GOOD DATA IN "OK1" ;& "OK2" TO THE START OF THE LAST GOOD 8 ;BYTE BLOCK. THIS BLOCK ALWAYS STARTS ON ;XXX0H ADDR IN FILE 1; IT MAY NOT IN FILE 2.) ; MOV A,L ANI 7 CZ EOBL ; ;ARE WE AT EOF (WHICH IS EITHER EOF LOCN ;OR END OF BUFFER)? CALL CKEOF1 JNZ COMP1 ;NO LDA EOF1FG ORA A JNZ EOFFND ;YES AND EOF LOADED, QUIT CALL EOBUF1 ; COMP1 CALL CKEOF2 JNZ COMP2 ;NO LDA EOF2FG ORA A JNZ EOFFND CALL EOBUF2 ; COMP2 JMP COMP ; ;FOUND A DIFFERENCE; ;IF EOF IS NOT IN BUFFER, FIRST FORCE ;BUFFER FILL IN ORDER TO AVOID HITTING ;EOBUF IN DIFFERENCE PROCESSING DIFFER LDA EOF1FG ORA A ;TEST 0 JNZ DIFF1 ;NOW SEE IF AT START OF BUFFER PUSH H LHLD OK1 CKEOB BUF1ST POP H CNZ EOBUF1 DIFF1 LDA EOF2FG ORA A JNZ DIFF2 XCHG PUSH H LHLD OK2 CKEOB BUF2ST POP H XCHG CNZ EOBUF2 ; ;IF WE ARE NOT AT START OF BLOCK IN FILE 1, ;STEP (STOP AT EOF) DIFF2 XCHG SHLD CURR2 ;SAVEDE XCHG MVI C,8 ;REPEAT 8 TIMES DIFF3 INX H;MOVE OFF SOB CALL GOSOB ;GO TO NEXT SOB XCHG LHLD CURR2 ;RESTORE DE XCHG ; ;NOW SEE IF WE ARE AT EOF IN EITHER FILE CALL CKEOF1 JZ DIFEOF CALL CKEOF2 JZ DIFEOF ; ;NOW FIND EXTEND OF DIFFERENCE. ;COMPARE CURRENT BLOCK IN FILE 1 TO ;FILE 2. ;HL POINTS TO CURRENT BLOCK IN FILE 1, ;DE IN FILE 2 ;INC DE UP TO 64 TIMES, COMPARING BYTE TO HL. ;IF A MATCH IS FOUND: ; INC HL ALSO; LOOK FOR 8 MATCHES IN A ROW. ; IF NOT FOUND RESTORE HL & CONTINUE. ; IF FOUND, EXIT. ;IF 64 INCREMENTS HIT, ;INC HL BY 8 & REPEAT TOTAL OF 8 TIMES. ;IF STILL NOT FOUND, GIVE UP. ;IF EOF HIT, EXIT. ; MVI B,64 ;8 BLOCKS OF 8 BYTES ; DIFF4 LDAX D CMP M CZ BYTEM JZ MATCH INX D CALL CKEOF2 JZ DIFEOF DCR B JNZ DIFF4 ; ;NOT FOUND, NEXT BLOCK DCR C JNZ DIFF3 ; ;STILL NO MATCH FOUND. PRINT 8 BLOCKS ;FROM EACH BUFFER & EXIT. ; ;WE HAVE A DIFFERENCE AND ARE AT EOF IN A FILE ;PRINT FROM "LAST" POINTER TO EOF IN BOTH BUFFERS ;(STOP AFTER 8 BLOCKS) DIFEOF LDA ERFLG ORA A ;TEST ERROR FLAG JNZ DIFE1 INR A ;SET IT STA ERFLG PRINT <'FILES UNEQUAL',0DH,0AH> DIFE1 PRINT <'****** FILE 1:',0DH,0AH> ;PRINT FILE 1 FROM "LAST OK" LHLD EOF1 XCHG LHLD OK1 CALL PRBUF PRINT <'*** FILE 2:',0DH,0AH> LHLD EOF2 XCHG LHLD OK2 CALL PRBUF JMP EXIT ; ;BYTEM--HAVE MATCHING BYTE, MOVING DE IN ;ONE BUFFER, MATCHES HL IN OTHER BUFFER. ;WANT TO FIND 7 MORE MATCHING BYTES IN A ROW. ;RET Z IF SO. BYTEM PUSH H PUSH D PUSH B MVI B,7 ;MATCH 7 BYTES BML INX H INX D LDAX D CMP M JNZ BM2 DCR B JNZ BML ;HAVE 7 MORE MATCHED BYTES (& Z SET) BM2 POP B POP D POP H RET ; ;PRBUF--PRINT BUFFER (AT HL) FOR 9 BLOCKS OR EOF ;ENTER WITH EOF ADDR IN DE PRBUF MVI B,9 PRBUF1 PUSH B CALL PRBLK ;PRINT BLOCK POP B JZ PREOF ;AT EOF? DCR B ;COUNT BLOCK JNZ PRBUF1 RET ; ;PREOF--AT EOF IN PRINT PREOF PRINT <'*EOF',0DH,0AH> RET ; ;PRBLK--PRINT BLOCK FROM HL ;LIMIT IN DE--RET Z IF HIT PRBLK SHLD TEMP ;SAVE HL MVI B,8 ;8 BYTES PRBLK1 CALL CMPHD RZ MOV A,M INX H ;DISPLAY A IN HEX PUSH PSW RRC ;SHIFT RIGHT 4 RRC RRC RRC CALL TAD POP PSW CALL TAD MVI A,' ' CALL TYPE DCR B JNZ PRBLK1 ; ;NOW DISPLAY LINE IN ASCII ('.' IF NOT PRINTABLE) LHLD TEMP MVI B,8 ;8 BYTES PRBLK2 MOV A,M INX H CPI 80H JNC NOPR CPI 20H JNC PRBLK3 ; NOPR MVI A,'.' ;SUB '.' FOR NON-PRINTING PRBLK3 CALL TYPE DCR B JNZ PRBLK2 CALL CRLF INR A ;CLEAR Z FLAG RET ; ;TAD--TRANSLATE HEX TO ASCII & DISPLAY TAD ANI 0FH ;MASK ADI 90H DAA ACI 40H DAA CALL TYPE RET ; CRLF MVI A,CR CALL TYPE MVI A,LF ; ;TYPE--DISPLAY CHAR IN A TYPE PUSH B PUSH D PUSH H PUT CON POP H POP D POP B RET ; ;MATCH: HAVE A MATCHED BLOCK. HL & DE POINT ;TO START OF BLOCK. ;PRINT FROM OK1 & OK2 TO END OF DIFF. ;UPDATE OK1 & OK2 & RETURN TO COMPARE. MATCH PUSH H PUSH D SHLD CURR1 ;TEMP STORAGE XCHG SHLD CURR2 ; ;PRINT THE BUFFERS LDA ERFLG ORA A ;TEST ERROR FLAG JNZ MAT1 INR A ;SET IT STA ERFLG PRINT <'FILES UNEQUAL',0DH,0AH> MAT1 PRINT <'****** FILE 1:',0DH,0AH> LHLD CURR1 XCHG ;DE POINTS TO END OF BUFF1 TO BE PRINTED LHLD OK1 CALL PRTOLM PRINT <'*** FILE 2:',0DH,0AH> LHLD CURR2 ;NOW BUFF 2 XCHG LHLD OK2 CALL PRTOLM ; ;NOW UPDATE OK1, OK2, POINTERS LHLD CURR1 SHLD OK1 LHLD CURR2 SHLD OK2 POP D POP H JMP COMP ;RETURN TO COMPARE LOOP ; ;PRTOLM--PRINT FROM HL TO LIMIT IN DE PRTOLM CALL PRBLK JNZ PRTOLM ;NOT DONE RET ; ;EOBL--MOVE POINTERS TO "LAST OK BLOCKS" EOBL PUSH H PUSH D CALL RETSBL ;BACK UP TO PREVIOUS LINE SHLD OK1 ;SAVE IT XCHG CALL RETSBL SHLD OK2 POP D POP H RET ; ;EOBUF1-END OF BUFFER 1 ;COPY FROM "LAST OK BLOCK" POINTER THRU END ;OF BUFFER, TO START OF BUFFER; ;REFILL REST OF BUFFER ;KEEP POINTER TO CURRENT BYTE (NOW AT EOBUF) EOBUF1 REFILL BUF1ST,OK1,CKEOB1,CURR1 ; ;NOW FILL BUFFER XCHG GETF ,,GETFILE1,EOF1FG,,EOF1 ; ;SET UP POINTER OK1 LXI H,BUF1ST SHLD OK1 LHLD CURR1 ;NEW BUFFER PTR POP D ;RECOVER RET ; ;EOBUF2--END OF BUFFER2 EOBUF2 XCHG REFILL BUF2ST,OK2,CKEOB2H,CURR2 XCHG GETF ,,GETFILE2,EOF2FG,,EOF2 LXI H,BUF2ST SHLD OK2 LHLD CURR2 XCHG POP H RET ; ;CKEOB1--SEE IF HL IS AT END OF BUFF1 ;(RET Z IF SO) CKEOB1 CKEOB BUF1EN RET ; ;CKEOF1--SEE IF HL IS AT END OF FILE1 ;(EOBUF OR LOADED EOF) ;(RET Z IF SO) CKEOF1 CKEOF EOF1 RET ; ;CKEOF2--SEE IF DE IS AT END OF FILE2 CKEOF2 XCHG CKEOF EOF2 XCHG RET ; ;CKEOB2H--SEE IF HL IS AT END OF BUFF2 CKEOB2H CKEOB BUF2EN RET ; ;EOFFND--AT EOF IN VALID COMPARE ;IF NO ERROR FLAG, PRINT OK & EXIT ;ELSE JUST EXIT EOFFND LDA ERFLG ORA A ;SET FLAGS JZ AOK JMP EXIT ; ;A-OK - FILES MATCH ; AOK PRINT 'FILES MATCH' EXIT RST 0 ;RET TO CP/M ; ERXIT POP D ;GET MESSAGE MVI C,@MSG CALL @BDOS JMP EXIT ; ;RETSBL--RET HL TO START OF BLOCK RETSBL DCX H ;BACK TO PREV BLOCK MOV A,L ANI 0F8H MOV L,A RET ; ;GOSOB--INC HL TO START OF NEXT BLOCK OR EOF ;IN FILE 1 GOSOB MOV A,L ANI 7 RZ ;THERE INX H CALL CKEOF1 RZ JP GOSOB ; ;CMPHD--COMPARE HL TO DE ;RETS Z IF EQ, C IF HL>DE CMPHD MOV A,D SUB H RNZ MOV A,E SUB L RET ; ;MOVE FROM (DE) TO (HL) LENGTH IN B MOVER LDAX D MOV M,A INX D INX H DCR B JNZ MOVER RET ; ;DATA STORAGE DS 80 ;STACK STACK EQU $ OK1 DS 2 ;LAST VALID LINE, FILE1 OK2 DS 2 CURR1 DS 2 ;CURRENT LINE IN SEARCH CURR2 DS 2 ERFLG DB 0 ;ERROR FLAG EOF1 DS 2 ;EOF ADDR EOF2 DS 2 EOF1FG DB 0 ;EOF FLAGS EOF2FG DB 0 TEMP DS 2 ORG ($+15) AND 0FFF0H ;TO 16 BYTE BOUNDARY BUF1ST DS 8192 BUF1EN BUF2ST DS 8192 BUF2EN BUFFERS EQU $ MEMSIZE EQU BUFFERS+@NXTB END