I have to do a simple CRC check for the following: Take an 8-bit input from a port, get it's CRC checksum value and output it. So far, I can take the input and I read the algorithm, so I append n - 1 zeros to my input, effectively making it big enough to be 16 bit. I got that working as well and I know I'll need a XOR here as we do a modulo 2 while dividing. But, I can't go any further with the algorithm, don't know where to even start.
.MACRO INITSTACK
LDI R16, HIGH(RAMEND)
OUT SPH, R16
LDI R16, LOW(RAMEND)
OUT SPL, R16
.ENDMACRO
.MACRO LOADIO
LDI R20, @1
OUT @0, R20
.ENDMACRO
.include "m128def.inc"
.EQU ones = 0xFF ; output
.EQU zeros = 0x00 ; input
.EQU CRC_CODE = 0x13 ; our CRC polynomial in binary (10011)
.DEF INPUTREG = R16 ; input register
.DEF CRC_RES = R17 ; Holds the CRC result (4 bits)
.DEF OPREG1 = R18 ; temp operation register 1
.DEF OPREG2 = R19 ; temp operation register 2
.DEF OPREG3 = R20 ; temp operation register 3
.DEF OPREG4 = R21 ; temp operation register 4
.DEF OPREG5 = R22 ; temp operation register 5
.ORG 0x0000
main:
INITSTACK
; Modifies the INPUTREG
RCALL TakeInput
RCALL CreateCRC
LOADIO DDRA, ones
LOADIO DDRB, ones
OUT PORTA, CRC_RES
Stop:
NOP
JMP Stop
TakeInput:
LOADIO DDRA, zeros
IN INPUTREG, PORTA
CLR XH
MOV XL, INPUTREG
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
LSL XL ; do a shift 4 times, for the 4 (5 - 1) zeros
ROL XH
RET
CreateCRC:
LDI OPREG1, 0x08 ; do shift 8 times
LDI OPREG2, CRC_CODE ; load the polynom
LSL OPREG2 ; no need for 5th bit, we only do operation with lower 4 bits (CLC does XOR for the high bit we skipped)
SWAP OPREG2 ; Swap nibbles, so the number has the bits we want at higher 4 bits
CLZ
crc_loop:
CLC
ROL INPUTREG
DEC OPREG1
BREQ crc_end ; if we did this 8 times, stop
BRCC crc_loop ; no carry, then keep shifting, if its set we go to XOR
crc_do_xor:
EOR INPUTREG, OPREG2
JMP crc_loop
crc_end:
SWAP INPUTREG ; Swap the higher 4 bits to lower 4 bits
MOV CRC_RES, INPUTREG
RET
EDIT: Now I get an incorrect result for the message 1100 1111 with code 10011. Output should be 1100 but I get 1101. Where could it be wrong?
答案 0 :(得分:2)
您的代码似乎没有任何有用的东西。您需要考虑算法的工作原理,并决定使用所需字节的好方法。
由于您的输入只是一个字节而不是一个流,我建议您使用该字节并执行8次移位。我建议你使用ROL,左转通过进位,CLC,清除进位,以及XOR指令。
想法是清除进位标志,然后向左旋转一个位置。如果进位位置1,则需要使用00110000执行XOR指令。这是没有前1位的多项式,向左移位。
1) 11001111 CLC and ROL
2) 10011110 with C=1, so do an XOR
10101110 CLC and ROL
3) 01011100 with C=1, so do an XOR
01101100 CLC and ROL
4) 11011000 with C=0, so don't XOR.
CLC and ROL
5) 10110000 with C=1, so do an XOR
01000000 CLC and ROL
6) 10000000 with C=0, so don't XOR.
CLC and ROL
7) 00000000 with C=1, so do an XOR
00110000 CLC and ROL
8) 01100000 with C=0, so don't XOR.
CLC and ROL
9) 11000000 The first four bits are the result. SWAP to get it to the right.
编写一个执行此算法的循环,测试C位以进行分支。请注意,多项式的高位不需要直接使用。这意味着,如果进位位置1,则只对低位进行异或。 CLC对进位位本身进行“异或”。