简体   繁体   English

装配AVR ATMEGA128:CRC算法

[英]Assembly AVR ATMEGA128: CRC Algorithm

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. 我必须对以下内容执行简单的CRC检查:从端口获取8位输入,获取其CRC校验和值并将其输出。 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. 到目前为止,我可以接受输入并读取算法,因此将n-1个零附加到我的输入中,有效地使其大到足以成为16位。 I got that working as well and I know I'll need a XOR here as we do a modulo 2 while dividing. 我也能正常工作,我知道我需要一个XOR,因为我们在除法的同时做模2。 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? 编辑:现在我得到错误的消息1100 1111与代码10011的结果。输出应为1100,但我得到1101。在哪里可能出错?

Your code doesn't seem to have anything useful yet. 您的代码似乎还没有什么用。 You need to think about how the algorithm works, and decide on a good way to use the bytes you need. 您需要考虑算法的工作原理,并确定使用所需字节的好方法。

Since your input is only a single byte instead of a stream, I suggest you work with that byte and perform the shift 8 times. 由于您的输入仅是一个字节而不是流,因此我建议您使用该字节并执行8次移位。 I suggest you use ROL, rotate left through carry, and CLC, clear carry bit, as well as an XOR instruction. 我建议您使用ROL,通过进位向左旋转,并使用CLC,清除进位,以及XOR指令。

The idea is to clear the carry flag, then rotate left one position. 这个想法是清除进位标志,然后向左旋转一个位置。 If the carry bit is set, then you need to do an XOR instruction with 00110000. This is the polynomial without the first 1, shifted to the left. 如果进位位已设置,则需要对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.

Write a loop that does this algorithm, testing the C bit for branching. 编写一个执行此算法的循环,测试C位的分支。 Notice that the high bit of the polynomial doesn't need to be used directly. 注意,多项式的高位不需要直接使用。 It is implied, in that you only XOR the lower bits if the carry bit is set. 这意味着,如果设置了进位,则只能对低位进行XOR。 CLC does the "XOR" for the carry bit itself. CLC对进位位本身执行“ XOR”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM