10
20
30 :
40 DIM mem% &FFF:OSCLI"LOAD CRCs/htm "+STR$~mem%:num%=&A6D
50
60 :
70 @%=&90A
80 PRINT"BASIC CRC-16: ";:S%=0:T%=TIME:PROCcrc:T%=TIME-T%
90 PRINT"&";~S%;" in ";T%/100;"s"'
100 :
110 @%=&2040A
120 PROCAsm1
130 PRINTA$;" CRC-16: ";:T%=TIME:FOR L%=1 TO N%:S%=0:PROCcrcAsm:NEXT:T%=TIME-T%
140 PRINTSPC(5-LENA$)"&";~S%;" in ";T%/100/N%;"s"'
150 :
160 PROCAsm2
170 PRINTA$;" CRC-16: ";:T%=TIME:FOR L%=1 TO N%:S%=0:PROCcrcAsm:NEXT:T%=TIME-T%
180 PRINTSPC(5-LENA$)"&";~S%;" in ";T%/100/N%;"s"'
190 :
200 @%=&90A
210 END
220 :
230 DEFPROCcopy
240 S%=0 :
250 REPEAT
260 num%=EXT#in%-PTR#in% :
270 IF num%>max% THEN num%=max%
280 PROCgbpb(rd%,in%,mem%,num%,0) :
290 PROCcrc :
300 PROCgbpb(wr%,out%,mem%,num%,0) :
310 UNTIL num%<max% :
320 ENDPROC
330 :
340
350 DEFPROCcrc:FORA%=mem%TOmem%+num%-1:S%=S%EOR256*?A%:FORB%=1TO8:S%=S%*2:IFS%AND&10000:S%=S%EOR&11021
360 NEXT:NEXT:ENDPROC
370 :
380
390 DEFPROCcrcAsm:!addr=mem%:!num=num%:!crc=S%:CALL Calc:S%=!crc:ENDPROC
400 :
410
420 DEFPROCAsm1
430 IFPAGE>&8000:IFINKEY-256=ASC"W":PROCcrc86:A$="80x86":N%=100:ENDPROC
440 IFPAGE>&8000:PROCcrcARM:A$="ARM":N%=10:ENDPROC
450 IF?&FFF7=&6C:PROCcrc65:A$="6502":N%=1:ENDPROC
460 IF?&FFF7=&C3:PROCcrc80:A$="Z80":N%=1
470 ENDPROC
480 :
490 DEFPROCAsm2
500 IFPAGE>&8000:END
510 IF?&FFF7=&6C:PROCcrc65ac:A$="ACORN":ENDPROC
520 END
530 ENDPROC
540 :
550 DEFPROCcrc65:DIM Calc 63:addr=&70:num=&72:crc=&74:FORP=0TO1
560 P%=Calc:[OPT P*2
570 .bytelp
580 LDX #8 :\ Prepare to rotate CRC 8 bits
590 LDA (addr-8 AND &FF,X) :\ Fetch byte from memory
600 :
610 \ The following code updates the CRC with the byte in A ---------+
620 \ If used in isolation, requires LDX #8 here |
630 EOR crc+1 :\ EOR byte into CRC top byte |
640 .rotlp :\ |
650 ASL crc+0:ROL A :\ Rotate CRC clearing bit 0 |
660 BCC clear :\ b15 was clear, skip past |
670 TAY :\ Hold CRC high byte in Y |
680 LDA crc+0:EOR #&21:STA crc+0 :\ CRC=CRC EOR &1021, XMODEM polynomic
690 TYA:EOR #&10 :\ Get CRC high byte back from Y |
700 .clear :\ b15 was zero |
710 DEX:BNE rotlp :\ Loop for 8 bits |
720 STA crc+1 :\ Store CRC high byte |
730 \ ---------------------------------------------------------------+
740 :
750 INC addr+0:BNE next:INC addr+1 :\ Step to next byte
760 .next
770 :
780 \ Now do a 16-bit decrement
790 LDA num+0:BNE skip :\ num.lo<>0, not wrapping from 00 to FF
800 DEC num+1 :\ Wrapping from 00 to FF, dec. high byte
810 .skip
820 DEC num+0:BNE bytelp :\ Dec. low byte, loop until num.lo=0
830 LDA num+1:BNE bytelp :\ Loop until num=0
840 RTS
850 ]:NEXT:ENDPROC
860 :
870 DEFPROCcrc65ac:DIM Calc2 79:addr=&70:num=&72:crc=&74:FORP=0TO1
880 H=crc+1:L=crc
890 P%=Calc:[OPT P*2 :\ Acorn CFS/RFS sample code
900 LDY #0 :\ Point to first byte
910 .bytelp
920 LDA (addr),Y :\ Fetch byte from memory
930 :
940 \ The following code updates the CRC with the byte in A ---------+
950 EOR H:STA H:LDX #8 :\ EOR byte into CRC top byte |
960 .rotlp :\ |
970 LDA H:ROL A:BCC clear :\ b15 clear, skip past |
980 LDA H:EOR #8:STA H :\ CRC=CRC EOR &0810, ACORN polynomic
990 LDA L:EOR #&10:STA L :\ |
1000 .clear :\ b15 was clear |
1010 ROL L:ROL H :\ Rotate CRC, rotating b15 into b0 |
1020 DEX:BNE rotlp :\ Loop for 8 bits |
1030 \ ---------------------------------------------------------------+
1040 :
1050 INY:BNE next:INC addr+1 :\ Step to next byte
1060 .next
1070 :
1080 \ Now do a 16-bit decrement
1090 LDA num+0:BNE skip :\ num.lo<>0, not wrapping from 00 to FF
1100 DEC num+1 :\ Wrapping from 00 to FF, dec. high byte
1110 .skip
1120 DEC num+0:BNE bytelp :\ Dec. low byte, loop until num.lo=0
1130 LDA num+1:BNE bytelp :\ Loop until num=0
1140 RTS
1150 ]:NEXT:ENDPROC
1160 :
1170 :
1180 DEFPROCcrc80:DIM Calc 79:addr=&70:num=&72:crc=&74:FORP=0TO1
1190 P%=Calc:[OPT P*2
1200 LD HL,(addr):LD BC,(num) :\ Address, Count
1210 LD DE,(crc) :\ Incoming CRC
1220 :
1230 \ Enter here with HL=>data, BC=count, DE=incoming CRC
1240 .bytelp
1250 PUSH BC :\ Save count
1260 LD A,(HL) :\ Fetch byte from memory
1270 :
1280 \ The following code updates the CRC with the byte in A ---------+
1290 XOR D :\ XOR byte into CRC top byte |
1300 LD B,8 :\ Prepare to rotate 8 bits |
1310 .rotlp :\ |
1320 SLA E:ADC A,A :\ Rotate CRC |
1330 JP NC,clear :\ b15 was zero |
1340 LD D,A :\ Put CRC high byte back into D |
1350 LD A,E:XOR &21:LD E,A :\ CRC=CRC XOR &1021, XMODEM polynomic |
1360 LD A,D:XOR &10 :\ And get CRC top byte back into A |
1370 .clear :\ |
1380 DEC B:JP NZ,rotlp :\ Loop for 8 bits |
1390 LD D,A :\ Put CRC high byte back into D |
1400 \ ---------------------------------------------------------------+
1410 :
1420 INC HL :\ Step to next byte
1430 POP BC:DEC BC :\ num=num-1
1440 LD A,B:OR C:JP NZ,bytelp :\ Loop until num=0
1450 LD (crc),DE :\ Store outgoing CRC
1460 RET
1470 ]:NEXT:ENDPROC
1480 :
1490 DEFPROCcrcARM:DIM Calc 87:FORP=0TO1
1500 P%=Calc:[OPT P*2
1510 LDR R0,addr:LDR R1,num :\ Address, Count
1520 LDR R2,crc :\ Incoming CRC
1530 \
1540 \ Enter here with R0=addr, R1=num, R2=crc
1550 \
1560 .crc16reg
1570 MOV R2,R2,LSL #16 :\ Move CRC to top of register
1580 LDR R3,xor :\ ZIP polynomic
1590 .bytelp
1600 LDRB R4,[R0],#1 :\ Get byte, inc address
1610 :
1620 \ The following code updates the CRC with the byte in R4 -----------+
1630 \ If used in isolation, requires LDR R3,xor here |
1640 EOR R2,R2,R4,LSL #24 :\ EOR byte into CRC top byte |
1650 MOV R4,#8 :\ Prepare to rotate 8 bits |
1660 .rotlp :\ |
1670 MOVS R2,R2,LSL #1 :\ Rotate CRC |
1680 EORCS R2,R2,R3 :\ If b15 was set, EOR with ZIP polynomic
1690 SUBS R4,R4,#1:BNE rotlp :\ Loop for 8 bits |
1700 \ ------------------------------------------------------------------+
1710 :
1720 SUBS R1,R1,#1:BNE bytelp :\ Loop until num=0
1730 MOV R2,R2,LSR #16:STR R2,crc :\ Store outgoing CRC
1740 MOV R15,R14
1750 .xor:EQUD &10210000 :\ ZIP polynomic
1760 .addr:EQUD 0:.num:EQUD 0
1770 .crc:EQUD 0
1780 ]:NEXT:ENDPROC
1790 :
1800 DEFPROCcrc86:DIM Calc 71:FORP=0TO1
1810 P%=Calc:[OPT P*2
1820 .crc16
1830 MOV ESI,[addr] ; ESI=>start of data
1840 MOV EBX,[num] ; EBX= length of data
1850 MOV ECX,[crc] ; ECX= incoming CRC
1860 SHL ECX,16 ; Move CRC into b16-b31
1870 ;
1880 .bytelp
1890 MOV AL,[ESI] ; Fetch byte from memory
1900 ;
1910 ; The following code updates the CRC with the byte in AL -----+
1920 SHL EAX,24 ; Move byte to b8-b15 |
1930 XOR ECX,EAX ; XOR byte into top of CRC |
1940 MOV AL,8 ; Prepare to rotate 8 bits |
1950 .rotlp ; |
1960 SHL ECX,1 ; Rotate CRC |
1970 JNC clear ; b15 was zero |
1980 XOR ECX,&10210000 ; If b15 was set, XOR with XMODEM polymonic
1990 .clear ; |
2000 DEC AL:JNZ rotlp ; Loop for 8 bits |
2010 ; ------------------------------------------------------------+
2020 ;
2030 INC SI ; Point to next byte
2040 DEC EBX:JNE bytelp ; num=num-1, loop until num=0
2050 SHR ECX,16 ; Move CRC back into b0-b15
2060 MOV [crc],ECX ; Store outgoing CRC
2070 RETF
2080 .addr:DD 0
2090 .num:DD 0
2100 .crc:DD 0
2110 ]:NEXT:ENDPROC
2120 :