基于奇偶位校验的位序列错误检测(x86汇编)问题排查
修复奇偶校验位序列检测的x86汇编+C代码问题
问题背景
我们需要实现一个位序列奇偶校验检测功能:每n个数据位后跟随1个奇校验位(前n位中1的个数为奇数时,校验位为1),输入为BYTE数组、位序列长度(恒为n+1的倍数)、n值,输出1表示存在错误,0表示无错误。现有混合x86汇编的C代码在测试案例(输入数组0xAD、0xDC,位长16,n=15)中无法正确运行,核心问题是奇偶位处理逻辑错误,未匹配前序数据位的奇偶计算结果。
常见错误根源
- 位顺序遍历错误:未严格按照BYTE内从最低有效位(LSB,第0位)到最高有效位(MSB,第7位)的顺序遍历,导致位序列完全错乱
- 校验位与数据位混淆:处理时误将校验位计入数据位的1的个数统计,或者提前读取校验位导致逻辑错位
- 奇校验逻辑错误:错误判断预期校验位的值(比如搞反奇偶对应的校验位取值)
- 边界位处理失误:最后一个BYTE仅使用部分位时,未精准停止遍历,导致多算无关位
修复后的代码
#include <stdint.h> typedef unsigned char BYTE; typedef unsigned int DWORD; BYTE check_parity_error(const BYTE* data, DWORD bit_length, BYTE n) { DWORD total_groups = bit_length / (n + 1); BYTE error = 0; __asm { mov esi, data ; ESI指向输入BYTE数组 mov ecx, total_groups ; ECX存储需要处理的校验组数 xor edx, edx ; EDX跟踪当前处理的全局位索引 xor ebx, ebx ; EBX存储当前组内数据位的1的计数 group_start: cmp ecx, 0 je check_end ; 所有组处理完成,退出 dec ecx ; 重置当前组的1计数,准备处理n个数据位 mov bl, 0 mov eax, n ; EAX存储当前组需要处理的数据位数量 data_bit_process: cmp eax, 0 je parity_check ; 数据位处理完毕,开始校验位检查 dec eax ; 计算当前位所在的字节索引和字节内位偏移 mov edi, edx shr edi, 3 ; 字节索引 = 全局位索引 / 8 mov cl, dl and cl, 7 ; 字节内位偏移 = 全局位索引 % 8 ; 提取当前位的值 mov al, [esi + edi] shr al, cl and al, 1 ; 更新1的计数 add bl, al inc edx ; 全局位索引+1,处理下一个数据位 jmp data_bit_process parity_check: ; 提取当前组的校验位 mov edi, edx shr edi, 3 mov cl, dl and cl, 7 mov al, [esi + edi] shr al, cl and al, 1 ; AL存储实际校验位的值 ; 计算预期校验位:奇校验,数据位1的个数为奇数则预期1,否则0 test bl, 1 mov ah, 1 ; 默认预期为1(奇数个1) jnz expected_match mov ah, 0 ; 偶数个1,预期校验位为0 expected_match: ; 对比实际与预期校验位 cmp al, ah je parity_ok ; 校验通过,处理下一组 mov error, 1 ; 校验失败,标记错误并退出 jmp check_end parity_ok: inc edx ; 跳过校验位,进入下一组 jmp group_start check_end: } return error; }
修复关键点说明
- 严格按LSB→MSB遍历:通过
全局位索引 % 8获取字节内的位偏移,shr al, cl精准提取对应位,确保位序列顺序完全符合要求 - 分离数据位与校验位处理:先完整处理每组的
n个数据位并统计1的个数,再单独提取校验位进行对比,避免逻辑混淆 - 准确的奇校验逻辑:通过
test bl, 1判断数据位1的个数的奇偶性,生成对应的预期校验位值,确保和规则完全匹配 - 精准位跟踪:用全局位索引
edx逐位推进,即使最后一个BYTE仅使用部分位,也能准确停止遍历,不会处理无关位
故障案例测试验证
针对测试输入BYTE数组[0xAD, 0xDC]、位长16、n=15:
- 总组数为
16/(15+1)=1,即15个数据位+1个校验位 - 从LSB开始的15个数据位依次为:0xAD的第0-7位(1,0,1,1,0,1,0,1)、0xDC的第0-6位(0,0,1,1,1,0,1)
- 统计1的个数:共10个(偶数),预期校验位为0
- 实际校验位是0xDC的第7位(二进制
11011100的最高位为1),与预期不符,代码返回1(错误),符合预期逻辑
内容的提问来源于stack exchange,提问作者Larcketto
相关产品推荐
相关产品推荐

