给定一个位序列,知道(数据的)每 n 位都有一个奇偶校验位(如果前 n 个中设置为 1 的位数是奇数,则为 1),检查是否有错误。注意: • 以位为单位的长度被指定为输入:可能会发生数组的最后一个字节仅被部分使用的情况。 • 可以假设比特序列的长度始终是(n+1)的倍数。 • 应从最低有效位到最高有效位分析字节内的位。
输入:BYTES 数组(视为位序列), 一个 DWORD(位序列的长度),一个 BYTE(n 的值)。 输出:一个 BYTE(如果有错误则包含 1,否则包含 0)。我尝试写这个,在某些情况下有效,但在其他情况下(例如给定的输入)却不起作用。
#include <stdio.h>
void main() {
// Input
unsigned char vet[] = { 0xAD,0xDC }; // Test array
unsigned int len = 16; // Length (number of bits)
unsigned char n = 15; // Number of data bits
// Output
unsigned char errors = 0; // 1 = errors; 0 = no errors
__asm {
XOR ECX, ECX // ECX serves as a bit counter
LEA ESI, vet // ESI points to the beginning of the array
MOV EBX, len // EBX contains the length of the bit sequence
MOV AL, n // AL contains the value of n (number of data bits)
ADD AL, 1 // Increment AL to include the parity bit
XOR EDX, EDX // EDX will be used for counting bits set to 1
check_next_bit:
CMP ECX, EBX // Compare the counter with the sequence length
JGE done_checking // If the counter is greater or equal, finish
MOV EDI, ECX // EDI is the current index
SHR EDI, 3 // Divide by 8 to find the correct byte
MOVZX EAX, BYTE PTR[ESI + EDI] // Load the current byte into EAX
MOV EDI, ECX
AND EDI, 7 // Get the position of the bit within the byte
SHR EAX, CL // Shift right to get the required bit
AND EAX, 1 // Isolate the least significant bit
CMP CL, n // Compare the counter with n (number of data bits)
JE check_parity // If equal, check the parity
ADD EDX, EAX // Add the current bit to EDX
INC CL // Increment the bit counter
JMP check_next_bit // Repeat the cycle for the next bit
check_parity:
AND EDX, 1 // Calculate the parity
CMP EDX, EAX // Compare the calculated parity with the expected parity bit
JNE set_error // If they don't match, set the error flag
XOR EDX, EDX // Reset the count of bits set to 1
INC CL // Increment the bit counter
JMP check_next_bit // Repeat the cycle for the next bit
set_error:
MOV errors, 1 // Set the error flag
JMP done_checking // Finish the checking
done_checking:
}
// Output to screen
printf("The bit sequence %scontains errors\n", (errors ? "" : "does not "));
}
我注意到汇编代码没有正确处理奇偶校验位。它应该检查奇偶校验位是否与前面位的奇偶校验计算相匹配,但似乎当前的实现没有按预期工作。
对于此类任务,您需要开发一个可以独立于其余代码运行的输入代码。下面的“位获取器”使用自己的一组寄存器 EAX、ESI 和 EDI,并通过进位标志输出单个位。
xor ebx, ebx
xor esi, esi ; Offset within the source array
xor edi, edi ; Counts number of cached (in AL) source bits
mov ecx, len ; ECX is outer loop counter (len) using step (n + 1)
OuterLoop:
mov bl, n
inc ebx ; EBX is inner loop counter (n + 1) using step (1)
sub ecx, ebx ; Outer loop step is taken early
xor edx, edx ; Counts number of ON bits
InnerLoop:
test edi, edi ; 'bit fetcher' \
jnz GetOneBit | This code operates
add edi, 8 | asynchronous to
movzx eax, byte ptr [vet + esi] ; Read one byte | the loops around it
inc esi ; and cache it in AL |
GetOneBit: | It would be nice to keep
dec edi ; Consume one bit | this in a subroutine
shr eax, 1 ; from AL -> CF /
adc edx, 0
dec ebx
jnz InnerLoop
and edx, 1 ; If bit 0 is ON, then there's a mismatch between
jnz Done ; Error EDX=1 calculated and stored parity bit
test ecx, ecx ; (*)
jnz OuterLoop
Done:
mov errors, dl ; DL=[0,1]
(*) 鉴于任务描述表明,无需查找不完整的记录; “可以假设比特序列的长度总是(n+1)的倍数。”