; Modified 8/24/85 for use with QuickBasic Compiler ; Heavy modifications 8/31/86 by Jim King ; Changed CRC_CALC from the awfulness it was to an algorithm suggested ; by Philip Burns. In a test program, this algorithm is over 3 times as ; fast as the one previously used by RBBS-PC. ; Changed the loop that calculates checksum and calls the CRC to be more ; efficient (just about halved the number of instructions). ; Note that RBBS-PC.BAS was also modified so that it no longer tacks on ; two null bytes to the input string (they were necessary for the old CRC ; routine to work correctly). ; Once again, thanks to Philip Burns for suggesting the CRC algorithm. ; Many thanks also to John Souvestre, who helped me tweak the assembly ; routine to run even faster. XM_CALC SEGMENT PUBLIC 'CODE' ASSUME CS:XM_CALC PUBLIC XMODEM ; CHK_SUM DB 0 STRG_LEN DW 0 ;CHANGED TO LENGTH OF STRING PASSED STRG_LOC DW 0 STRG_MSG DB 1026 DUP (' ') ;COMMAND CHARS (+CR) GO INTO HERE ; ; ; XMODEM PROC FAR PUSH BP MOV BP,SP MOV CHK_SUM,0 ;INITIALIZE ; MOV SI,[BP+14] ;GET STRING DESCRIPTOR MOV BL,[SI+ 2] ;REARRANGE LOW/HIGH BYTES MOV BH,[SI+ 3] ;NOW BX HOLDS THE ADDRESS OF THE STRING MOV STRG_LOC,BX ;STORE IT MOV AX,[SI] ;GET STRING LENGTH MOV STRG_LEN,AX ;STORE IT ; MOV CX,STRG_LEN ;STORE LENGTH IN CX MOV SI,STRG_LOC ;STORE OFFSET TO STRING IN SI PUSH CS POP ES MOV DI,OFFSET STRG_MSG ;ES:DI = LOCATION OF VARIABLE REP MOVSB ;FILL STRG_MSG WITH STRING ; PUSH DS ;SAVE DS PUSH CS POP DS MOV CX,STRG_LEN ;INITIALIZE COUNTER MOV SI,OFFSET STRG_MSG ;get address of input string XOR DX,DX ;initialize CRC value to 0 LOOP1: LODSB ;get character into AL MOV DI,CX ;SAVE CX ADD CHK_SUM,AL ;ADD AL TO CHK_SUM ; this used to be: ;CRC_CALC PROC NEAR ; this is the CRC calculation routine. It's placed here instead of in ; a separate procedure for additional speed. ; DX contains the CRC value, AL has the new character. Other registers ; are used for temporary storage and scratch work. XCHG DH,DL ; CRC := Swap(CRC) XOR Ord(Ch); XOR DL,AL MOV AL,DL ; CRC := CRC XOR ( Lo(CRC) SHR 4 ); MOV CL,4 SHR AL,CL XOR DL,AL ; CRC := CRC XOR ( Swap(Lo(CRC)) SHL 4 ) ; XOR ( Lo(CRC) SHL 5 ); MOV BL,DL MOV AH,DL SHL AH,CL XOR DH,AH XOR BH,BH INC CL SHL BX,CL XOR DX,BX ; end of the CRC calculation routine MOV CX,DI ;RESTORE CX LOOP LOOP1 ;do it again POP DS ;RESTORE DS MOV BX,DX ;PASS BACK THE CRC VALUE MOV SI,[BP+ 6] ;AND CRC HIGH AND LOW BYTES MOV [SI],BL MOV SI,[BP+ 8] MOV [SI],BH MOV SI,[BP+10] MOV [SI],BX MOV BL,CS:CHK_SUM ;PASS BACK THE CHECK SUM MOV SI,[BP+12] MOV [SI],BL ; PUSH CS ;CLEAN UP WORK TO RETURN TO BASIC POP ES POP BP RET 10 XMODEM ENDP XM_CALC ENDS END