Correcting Hamming Code in ARM Assembly
AREA program, CODE
ENTRY
Main
LDR R11,=2_0000000000010011011111 ; word encoded in hamming code as 16 bits data, 5 parity, 1 Pall
AND R0,R11,#0x3F
MOV R0,R0,LSR #1 ; move the 5 parity bits to R0
MOV R1,R11,LSR #6 ; move the 16 data bits to R1
; build the Hamming encoding inserting the parity bits at 2^n positions
LDR R2,=1 ; current power of 2
LDR R3,=1 ; bit counter
LDR R4,=0 ; final hamming encoding
AND R6,R11,#1 ; get Pall in R6
LDR R7,=1 ; current power of 2 for parity
bloop
CMP R3,R7
BNE cpydat ; if the current bit is not a power of 2, skip
AND R5,R0,R2 ; get current parity bit
ORR R4,R4,R5 ; put bit in current bit position
MOV R1,R1,LSL #1 ; shift data bits
MOV R7,R7,LSL #1 ; get next power of 2 for parity
B next
cpydat
AND R5,R1,R2 ; get current data bit
ORR R4,R4,R5 ; put bit in current bit position
MOV R0,R0,LSL #1 ; shift parity bits
next
MOV R6,R6,LSL #1 ; advance Pall to msb
MOV R2,R2,LSL #1 ; get next power of 2
ADD R3,R3,#1 ; increment number of bits
CMP R3,#21 ; continue while we haven't built the 21 bit encoding
BLE bloop
ORR R4,R4,R6 ; add Pall to encoded word
MOV R0,R4
BL Parity ; calculate total parity
MOV R1,R0 ; R1=total parity
LDR R2,=0 ; R2 will contain the 5 parity bits
LDR R7,=4 ; calculate the 5 parity bits
LDR R5,=P0 ; load start address masks in R5
ploop
LDR R6,[R5,R7,LSL #2] ; load bit mask for calculating current P
AND R0,R4,R6 ; select the bits to use for calculating parity
BL Parity ; calculate parity
MOV R2,R2,LSL #1 ; shift old parity bits to the left
ORR R2,R2,R0 ; add current parity bit
SUBS R7,R7,#1
BGE ploop
CMP R2,#0
BEQ NOERR
CMP R1,#0
BEQ DBLERR
ONEERR
LDR R0,=1
shl
SUBS R2,R2,#1
BEQ endshl
MOV R0,R0,LSL #1 ; use R2 to get the erroneous position
B shl
endshl
EOR R4,R4,R0 ; invert erroneous bit
LDR R0,=msg3 ; print single error
SWI &2
MOV R0,R4 ; set corrected encoding in R0
B exit
DBLERR
LDR R0,=msg2 ; print double error
SWI &2
B exit
NOERR1
CMP R1,#0 ;
BEQ NOERR
ERR22 ; error in parity bit
LDR R0,=1
MOV R0,R0,LSL #21
EOR R4,R4,R0 ; invert bit
LDR R0,=msg1 ; print error Pall, corrected
SWI &2
MOV R0,R4 ; set corrected encoding in R0
B exit
NOERR
LDR R0,=msg0 ; print no error
SWI &2
MOV R0,R4 ; set corrected encoding in R0
exit
SWI &11 ; exit program
; calculate the parity of the word in R0 which is assumed to be 22 bits
Parity
STMIA SP!, {R4,R5,R14}
LDR R4,=0
LDR R5,=22 ; number of bits in the word
l1 ; loop to calculate total parity, saving it in R4
MOVS R0,R0,LSR #1 ; move the lsb to the carry
EORHS R4,R4,#1 ; XOR the current bit with the carry
SUBS R5,R5,#1 ; decrement number of bits to process
BNE l1 ; continue for all bits in word
MOV R0,R4 ; return parity
LDMDB SP!, {R4,R5,PC} ; restore registers and return
; positions in encoded word for calculating the parity bits
P0 DCD 2_101010101010101010101
P1 DCD 2_001100110011001100110
P2 DCD 2_110000111100001111000
P3 DCD 2_000000111111110000000
P4 DCD 2_111111000000000000000
msg0 DCB "No error detected.",10,0
msg1 DCB "Error in Pall detected and corrected.",10,0
msg2 DCB "Double error detected, can't be corrected.",10,0
msg3 DCB "Single error detected and corrected.",10,0
END