- UID
- 1029342
- 性别
- 男
|
其中,Qa00是整数,与余式无关;而Ra00和Tbc都是二字节序列,因而,它们的和(模2加法,即异或运算)仍然是二字节序列(二进制16位,小于生成多项式的17位),因此,它就是 Tabc的余式Rabc,即
(9)
这说明,可以把三字节序列Tabc=[ a b c ]的运算分解成两个步骤来进行,如图2所示。
1. 通过查余式表(表1),读取Ta00=[a 0 0 ]的余式Ra00=[ ha00 la00 ];
2. 将Ra00与[ b c ]进行异或运算,从而得到[ a b c ]的余式Rabc=[ habc labc ],即habc=ha00 Å b,labc=la00 Å c。
由于[a 0 0 ]中只有一个字节不为零,因此,[a 0 0 ]余式表仅需要256个单元,即占用512个字节。
图2 三字节序列[ a b c ]的计算办法
4 适用于51系列等单片机的算法
前面所述的办法可以直接用于51系列等单片机,因为512字节的余式表对它们的程序存储容量来说是完全不成问题的。
计算直接通过上述的递推过程来进行,每一次递推都是对一个三字节序列进行的计算:第一次是[ m1 m2 m3 ],结果是[ h3 l3 ];第二次是[ h3 l3 m4 ],结果是[ h4 l4 ];......,第i次是[ hi+1 li+1 mi+2 ],结果是[ hi+2 li+2 ];......;最后是[ hk+1 lk+1 mk+2 ],最终结果是[ h l ]。如果有k个数据字节,则递推k次。下面给出一个三字节序列计算子程序,供每一次递推运算时调用。注意,在第一次被调用之前,先将m1、 m2和m3分别存入R0、R1和R2中(子程序返回时,计算结果将存放在R0和R1中)。从第二次调用时开始,每次在调用之前只需先将参与本次运算的字节存入R2即可(第二次是m4,第三次是m5,...,第i次是mi+2,...)。当最后一次调用返回后,R0和R1分别存放的就是最终结果h和l 。
CRC MOV DPH, #table ; 指向余式表下半区
MOV DPL, R0 ; 指向对应单元
CLR A ;
MOVC A, @A+DPTR ; 读余式的高字节
XRL A, R1 ; 计算余式的高字节
MOV R0, A ; 存入R0
INC DPH ; 指向余式表上半区
CLR A ;
MOVC A, @A+DPTR ; 读余式的低字节
XRL A, R2 ; 计算余式的低字节
MOV R1, A ; 存入R1
RET
这一子程序只有12条指令,因此十分简捷,而且只占用16个机器周期,也就是说,相当于计算每一个字节只需16个机器周期即可完成,这将比传统的软件算法快十几倍。
表1 [ a 0 0 ] 余式表
a
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
0×
0000
1021
2042
3063
4084
50A5
60C6
70E7
8108
9129
A14A
B16B
C18C
D1AD
E1CE
F1EF
1×
1231
0210
3273
2252
52B5
4294
72F7
62D6
9339
8318
B37B
A35A
D3BD
C39C
F3FF
E3DE
2×
2462
3443
0420
1401
64E6
74C7
44A4
5485
A56A
B54B
8528
9509
E5EE
F5CF
C5AC
D58D
3×
3653
2672
1611
0630
76D7
66F6
5695
46B4
B75B
A77A
9719
8738
F7DF
E7FE
D79D
C7BC
4×
48C4
58E5
6886
78A7
0840
1861
2802
3823
C9CC
D9ED
E98E
F9AF
8948
9969
A90A
B92B
5×
5AF5
4AD4
7AB7
6A96
1A71
0A50
3A33
2A12
DBFD
CBDC
FBBF
EB9E
9B79
8B58
BB3B
AB1A |
|