汇编AVR ATMEGA128:CRC算法
Assembly AVR ATMEGA128: CRC Algorithm
我必须对以下内容进行简单的 CRC 检查:从端口获取一个 8 位输入,获取它的 CRC 校验和值并将其输出。到目前为止,我可以获取输入并读取算法,因此我将 n - 1 个零添加到我的输入中,有效地使其足够大到 16 位。我也得到了它的工作,我知道我在这里需要一个异或,因为我们在除法时做一个模 2。但是,我无法进一步研究该算法,甚至不知道从哪里开始。
.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
编辑:现在我得到的消息 1100 1111 的结果不正确,代码为 10011。输出应该是 1100,但我得到的是 1101。哪里错了?
您的代码似乎还没有任何用处。您需要考虑算法的工作原理,并决定使用所需字节的好方法。
由于您的输入只是一个字节而不是一个流,我建议您使用该字节并执行 8 次移位。我建议你使用 ROL,通过进位向左循环,和 CLC,清除进位,以及 XOR 指令。
思路是清除进位标志,然后向左循环一个位置。如果设置了进位,则需要与00110000进行异或指令。这是没有第一个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 位的分支。请注意,不需要直接使用多项式的高位。这意味着,如果设置了进位,您只能对低位进行 XOR。 CLC 为进位位本身执行 "XOR"。
我必须对以下内容进行简单的 CRC 检查:从端口获取一个 8 位输入,获取它的 CRC 校验和值并将其输出。到目前为止,我可以获取输入并读取算法,因此我将 n - 1 个零添加到我的输入中,有效地使其足够大到 16 位。我也得到了它的工作,我知道我在这里需要一个异或,因为我们在除法时做一个模 2。但是,我无法进一步研究该算法,甚至不知道从哪里开始。
.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
编辑:现在我得到的消息 1100 1111 的结果不正确,代码为 10011。输出应该是 1100,但我得到的是 1101。哪里错了?
您的代码似乎还没有任何用处。您需要考虑算法的工作原理,并决定使用所需字节的好方法。
由于您的输入只是一个字节而不是一个流,我建议您使用该字节并执行 8 次移位。我建议你使用 ROL,通过进位向左循环,和 CLC,清除进位,以及 XOR 指令。
思路是清除进位标志,然后向左循环一个位置。如果设置了进位,则需要与00110000进行异或指令。这是没有第一个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 位的分支。请注意,不需要直接使用多项式的高位。这意味着,如果设置了进位,您只能对低位进行 XOR。 CLC 为进位位本身执行 "XOR"。