home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol009
/
crck10-6.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
11KB
|
495 lines
;
; CRCK.ASM version 4.2
; by Keith Petersen, W8SDZ
; (revised 10/6/80)
;
;----> NOTE: MUST BE ASSEMBLED BY MAC <----
;
;CRCK is a program to read any CP/M file and print
;a CYCLIC-REDUNDANCY-CHECK number based on the
;CCITT standard polynominal:
; X^16 + X^15 + X^13 + X^7 + X^4 + X^2 + X + 1
;
;Useful for checking accuracy of file transfers.
;More accurate than a simple checksum.
;
;Optionally will write an output file to the default
;drive, listing the CRC's of all files checked in a
;single session.
;
;COMMANDS: CRCK [drive:]<filename.filetype> [F]
;
;Examples:
; CRCK MYFILE.ASM ;CHECK ONLY MYFILE.ASM
; CRCK *.ASM ;CHECK ALL .ASM FILES
; CRCK *.* F ;CHECK ALL FILES, MAKE FILE OF RESULTS
;
;Program updates/fixes (these are written in reverse
;order to minimize reading time to find latest update):
;
;10/06/80 FIX TO ERASE TEMPORARY FILE WHEN OUTPUT FILE IS
; REQUESTED AND NAME NOT FOUND IN DIRECTORY. (KBP)
;
;10/05/80 FIX ABORT ROUTINE TO CHECK FOR FILE REQUEST
; AND TO CLOSE INCOMPLETE FILE BEFORE ERASING
; IT. ADDED TESTS FOR NO FILE NAME AND FILE
; READ ERROR. (KBP)
;
;10/04/80 ADD ROUTINE TO GIVE OPTION TO MAKE
; DISK FILE OF CRC's. FIXED MFA ROUTINE
; SO FIRST-TIME FLAG NOW SHOWS IF NO FILE
; FOUND. (KBP)
;
;04/21/80 ADD MULTIPLE FILENAME FEATURE, PRINT
; NAME OF CURRENT FILE BEING READ, AND
; ALLOW OPERATOR ABORT. (KBP)
;
;08/20/79 FIX BUG IN READIT ROUTINE WHICH
; SHOWED UP ONLY ON ALTCPM OPTION. (KBP)
;
;08/19/79 ADD CONDITIONAL ASSEMBLY FOR CP/M
; ON H8 OR TRS-80. (KBP)
;
;06/27/79 FIRST WRITTEN BY KEITH PETERSEN, W8SDZ
;
;Define true and false
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
;Conditional assembly switches
;
STDCPM EQU TRUE ;TRUE IS STANDARD CP/M
ALTCPM EQU FALSE ;TRUE IS H8 OR TRS-80
NOSYS EQU FALSE ;TRUE IF SYS FILES NOT WANTED
;
;System equates
;
BASE SET 0
IF ALTCPM
BASE SET 4200H
ENDIF ;ALTCPM
;
;Define write buffer size (presently set for 8k)
;
BSIZE EQU 8*1024 ;DISK WRITE BUFFER SIZE
;
;BDOS equates
;
RDCON EQU 1
WRCON EQU 2
PRINT EQU 9
CSTAT EQU 11
OPEN EQU 15
SRCHF EQU 17
SRCHN EQU 18
READ EQU 20
STDMA EQU 26
BDOS EQU BASE+5
FCB EQU BASE+5CH
FCBEXT EQU FCB+12
FCBRNO EQU FCB+32
FCB2 EQU BASE+6CH
;
;Program starts here
;
ORG BASE+100H
;
MACLIB SEQIO ;DEFINE MACRO LIBRARY USED
;
CRCK: JMP BEGIN ;JUMP AROUND IDENTIFICATION
DB 'CRCK.COM 4.2 10/6/80'
;
BEGIN: LXI H,0 ;GET STACK...
DAD SP ;POINTER SO WE CAN...
SHLD STACK ;SAVE IT
LXI SP,STACK ;INITIALIZE LOCAL STACK
CALL CRLF ;TURN UP A NEW LINE
LDA FCB+1
CPI ' ' ;SEE IF NAME THERE
JNZ BEGIN2 ;YES, CONTINUE
CALL ERXIT ;PRINT MSG, THEN EXIT
DB '++NO FILE NAME SPECIFIED++',CR,LF,'$'
;
BEGIN2: CALL ILPRT ;PRINT:
DB 'CRCK ver 4.2',CR,LF
DB 'CTL-S pauses, CTL-C aborts',CR,LF,0
LDA FCB2+1 ;GET OPTION
STA FFLAG ;SAVE IT FOR LATER
CPI 'F' ;FILE WANTED?
JNZ AGAIN ;NO, SKIP FILE INIT
;
;'Declare' FCB for output file
;(temporarily named CRCKLIST.$$$)
;
FILE OUTFILE,CRCFILE,,CRCKLIST,$$$,BSIZE
;
AGAIN: LXI SP,STACK ;RE-INIT STACK POINTER
CALL MFNAME ;SEARCH FOR NAMES
JNC NAMTST ;ANOTHER FOUND, PRINT NAME
LDA MFFLG1 ;NOTHING FOUND, CHECK...
ORA A ;... FIRST TIME FLAG
JZ DONE ;AT LEAST ONE WAS FOUND
CALL ABEXIT ;PRINT MSG, THEN EXIT
DB '++FILE NOT FOUND++$'
;
DONE: LDA FFLAG ;SEE IF WE'RE MAKING FILE
CPI 'F'
JNZ DONE2 ;NO, SKIP THE FILE STUFF
;
;Close CRCKLIST.$$$
FINIS CRCFILE
;
;Build FCB for final name of CRCKLIST.CRC
FILE SETFILE,FINAL,,CRCKLIST,CRC
;
;Erase any existing old file
ERASE FINAL
;
;Rename CRCKLIST.$$$ to CRCKLIST.CRC
RENAME FINAL,CRCFILE
;
;Now exit to CP/M
DONE2: CALL MSGEXIT ;PRINT DONE, THEN EXIT
DB CR,LF,'DONE$'
;
;Test for names to ignore
;
NAMTST: IF NOSYS
LDA FCB+10 ;GET SYS ATTRIBUTE
ANI 80H ;IS IT SYS?
JNZ AGAIN ;YES, IGNORE THIS FILE
ENDIF ;NOSYS
;
;Ignore files with .$$$ filetype (they are usually
;zero-length and clutter up our display. We also
;want to ignore our own CRCKLIST.$$$ temporary file).
;
LXI H,FCB+9 ;POINT TO FILETYPE IN FCB
CALL TSTBAD ;CHECK FOR .$$$ FILES
JZ AGAIN ;IF ZERO FLAG, IGNORE THEM
;
;Move 8 characters from FCB+1 to FNAME
LXI H,FCB+1
LXI D,FNAME
LXI B,8
CALL MOVER
;Move 3 characters from FCB+9 to FNAME+9
LXI H,FCB+9
LXI D,FNAME+9
LXI B,3
CALL MOVER
;Now print filename.type
CALL ILPRT ;PRINT:
DB CR,LF,'--> FILE: '
FNAME: DB 'XXXXXXXX.XXX',TAB,TAB,'CRC = ',0
;
;Open the file
LXI D,FCB
MVI C,OPEN
CALL BDOS
INR A
JNZ RDINIT
CALL ABEXIT
DB '++OPEN FAILED++$'
;
;Initialize CRC to zero and set BUFAD to cause initial read
RDINIT: LXI H,0
SHLD REM ;INIT REMAINDER TO ZERO
LXI H,BASE+100H
SHLD BUFAD ;INIT BUFFER ADRS
;
;This is the read loop
READIT: LHLD BUFAD
MOV A,H ;TIME TO READ?
CPI BASE SHR 8
JZ NORD ;NO READ
MVI C,CSTAT
CALL BDOS ;CHECK FOR OPERATOR ABORT
ORA A
JZ READ2 ;NOTHING FROM OPERATOR
MVI C,RDCON
CALL BDOS ;GET CHARACTER INPUTTED
CPI 'C'-40H ;CONTROL C?
JZ ABEXT2 ;YES EXIT
;
READ2: LXI D,FCB
MVI C,READ ;READ ANOTHER SECTOR OF FILE
CALL BDOS
ORA A ;CHECK RETURN CODE
JNZ FINISH ;ERROR OR EOF
LXI H,BASE+80H ;BUFFER LOCATION
;
NORD: MOV A,M ;GET FILE CHARACTER
STA MESS ;SAVE FOR DIVP
INX H
SHLD BUFAD ;UPDATE BUFFER ADR
CALL DIVP ;CALCULATE NEW CRC
JMP READIT ;GO READ MORE CHARACTERS
;
FINISH: CPI 1 ;NORMAL END-OF-FILE?
JNZ FILERR ;NO, IT WAS A READ ERROR
LDA REM+1 ;GET MSP OF CRC
CALL HEXO ;PRINT IT
MVI A,' '
CALL TYPE ;TYPE A SPACE
LDA REM ;GET LSP OF CRC
CALL HEXO ;PRINT IT
CALL CRLF ;TURN UP NEW LINE
JMP AGAIN ;SEE IF MORE FILES TO DO
;
FILERR: CALL ABEXIT ;ABORT BECAUSE OF FILE READ ERROR
DB '++FILE READ ERROR++$'
;
;---------------------------------------------
;An 8080 routine for generating a CYCLIC-
;REDUNDANCY-CHECK. Character leaves that
;character in location REM. By Fred Gutman.
;From 'EDN' magazine, June 5, 1979 issue, page 84.
;
DIVP: LHLD REM ;GET REMAINDER
MOV A,H
ANI 128 ;Q-BIT MASK
PUSH PSW ;SAVE STATUS
DAD H ;2 X R(X)
LDA MESS ;MESSAGE BIT IN LSB
ADD L
MOV L,A
POP PSW
JZ QB2 ;IF Q-BIT IS ZERO
;
QB: MOV A,H
XRI 0A0H ;MS HALF OF GEN. POLY
MOV H,A
MOV A,L
XRI 97H ;LS HALF OF GEN. POLY
MOV L,A
;
QB2: SHLD REM
RET
;--------------------------------------------
;
;Hex output
;
HEXO: PUSH PSW ;SAVE FOR RIGHT DIGIT
RAR ;RIGHT..
RAR ;..JUSTIFY..
RAR ;..LEFT..
RAR ;..DIGIT..
CALL NIBBL ;PRINT LEFT DIGIT
POP PSW ;RESTORE RIGHT
;
NIBBL: ANI 0FH ;ISOLATE DIGIT
CPI 10 ;IS IS <10?
JC ISNUM ;YES, NOT ALPHA
ADI 7 ;ADD ALPHA BIAS
;
ISNUM: ADI '0' ;MAKE PRINTABLE
JMP TYPE ;PRINT IT, THEN RETURN
;
;Inline print routine
;
ILPRT: XTHL ;SAVE HL, GET MSG
;
ILPLP: MOV A,M ;GET CHAR
CALL TYPE ;OUTPUT IT
INX H ;POINT TO NEXT
MOV A,M ;TEST
ORA A ;..FOR END
JNZ ILPLP
XTHL ;RESTORE HL, RET ADDR
RET ;RET PAST MSG
;
;Send carriage return, line feed to output
;
CRLF: MVI A,CR ;CARRIAGE RETURN
CALL TYPE
MVI A,LF ;LINE FEED, FALL INTO 'TYPE'
;
;Send character in A register to output
;
TYPE: PUSH B
PUSH D
PUSH H
ANI 7FH ;STRIP PARITY BIT
MOV E,A
PUSH D
CALL WRFILE ;WRITE TO FILE IF REQUESTED
POP D
MVI C,WRCON ;SEND CHARACTER TO CONSOLE
CALL BDOS
POP H
POP D
POP B
RET
;
;Write character in E register to output file
;
WRFILE: LDA FFLAG ;GET FILE TRIGGER
CPI 'F' ;IS IT SET?
RNZ ;NO, RETURN
MOV A,E ;GET CHARACTER BACK
PUT CRCFILE ;SEND IT TO THE FILE
RET
;
;Multi-file access subroutine. Allows processing
;of multiple files (i.e. *.ASM) from disk. This
;routine builds the proper name in the FCB each
;time it is called. Carry is set if no more names
;can be found. The routine is commented in Pseudo
;code, each Pseudo code statement is in <<...>>
;
MFNAME: ;<<init DMA addr and FCB>>
MVI C,STDMA
LXI D,BASE+80H
CALL BDOS
XRA A
STA FCBEXT
STA FCBRNO
;<<if first time>>
LDA MFFLG1
ORA A
JZ MFN01
;<<save the requested name>>
;Save orig request
LXI H,FCB
LXI D,MFREQ
LXI B,12
CALL MOVER
LDA FCB
STA MFCUR ;SAVE DISK IN CURR FCB
;<<SRCHF requested name>>
LXI H,MFREQ
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHF
LXI D,FCB
CALL BDOS
;<<else>>
JMP MFN02
;
MFN01: ;<<SRCHF current name>>
LXI H,MFCUR
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHF
LXI D,FCB
CALL BDOS
;<<SRCHN requested name>>
LXI H,MFREQ
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHN
LXI D,FCB
CALL BDOS
;<<endif>>
MFN02: ;<<return carry if not found>>
INR A
STC
RZ
;<<move name found to current name>>
DCR A
ANI 3
ADD A
ADD A
ADD A
ADD A
ADD A
ADI 81H
MOV L,A
MVI H,BASE SHR 8
PUSH H ;SAVE NAME POINTER
LXI D,MFCUR+1
LXI B,11
CALL MOVER
;<<move name found to FCB>>
POP H
LXI D,FCB+1
LXI B,11
CALL MOVER
;<<setup FCB>>
XRA A
STA FCBEXT
STA FCBRNO
STA MFFLG1 ;TURN OFF 1ST TIME SW
;<<return>>
RET
;------------------------------------------------
;
;Check for .$$$ files
;
TSTBAD: CALL TESTIT ;CHECK FIRST ONE FOR '$'
RNZ ;NO, RETURN
CALL TESTIT ;CHECK SECOND ONE
RNZ ;NO, RETURN
;FALL INTO TESTIT TO CHECK THIRD
;
TESTIT: MOV A,M
ANI 7FH ;STRIP ATTRIBUTE
CPI '$' ;CHECK FOR $ FILETYPE
INX H
RET
;
;Move (BC) bytes from (HL) to (DE)
;
MOVER: MOV A,M
STAX D
INX H
INX D
DCX B
MOV A,B
ORA C
JNZ MOVER
RET
;
;Aborted - print reason. If making output file,
;close the incomplete file to update CP/M's bit map,
;then erase it.
;
ABEXIT: POP D ;GET MSG ADRS
MVI C,PRINT
CALL BDOS ;PRINT MSG
;
ABEXT2: LDA FFLAG ;SEE IF WE ARE MAKING FILE
CPI 'F'
JNZ ABEXT3 ;NO FILE, SKIP FILE STUFF
FINIS CRCFILE ;CLOSE INCOMPLETE FILE
ERASE CRCFILE ;ERASE INCOMPLETE FILE
;
ABEXT3: CALL ERXIT ;PRINT MSG, EXIT
DB CR,LF,CR,LF,'++ABORTED++$'
;
;Exit with message
;
MSGEXIT:EQU $ ;EXIT W/"INFORMATIONAL" MSG
ERXIT: POP D ;GET MSG
MVI C,PRINT
CALL BDOS
;
;Exit, restoring stack and return to CCP
;
EXIT: LHLD STACK
SPHL
RET ;TO CCP
;
;Program storage area
;
FFLAG: DB 0 ;FILE WRITE REQUEST FLAG
REM: DW 0 ;CRC REMAINDER STORAGE
MESS: DB 0 ;CRC MESSAGE CHAR GOES HERE
MFFLG1: DB 1 ;1ST TIME SWITCH
MFREQ: DS 12 ;REQUESTED NAME
MFCUR: DS 12 ;CURRENT NAME
BUFAD: DS 2 ;READ BUFFER ADDRESS
DS 60 ;STACK AREA
STACK: EQU $
OLDSTK: DS 2 ;OLD STACK POINTER SAVED HERE
;
;Define location of file write buffer
BUFFERS:EQU $
;
END CRCK