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