x86汇编代码调试求助:零比特子序列长度计算问题
汇编代码错误排查:全0子序列最小/最大长度计算
需求说明
给定比特序列,需计算其中全0子序列的最小和最大长度:
- 输入:字节数组(BYTE)、表示总比特数的WORD值
- 分析规则:从每个字节的**最低有效位(LSB)到最高有效位(MSB)**处理,最后一个字节可仅使用部分比特
- 输出:short int类型的
minLung(最小长度)和maxLung(最大长度);无全0子序列时,两者均返回-1 - 输入示例:
unsigned char vet[] = { 0xBC,0xFF,0x01 }; unsigned short int len = 18;
原代码中的错误点
1. 无全0子序列时,minLung未正确设为-1
在check_result段中,当检测到maxLung仍为初始值-1(即无全0子序列)时,代码仅将AX设为-1,但未将该值写入minLung,导致minLung保留初始的总比特数,不符合需求。
2. 32位与16位寄存器混合比较导致符号错误
maxLung是16位short int,初始值为-1(二进制0xFFFF)。在更新maxLung时,代码使用32位寄存器EDI(计数器)与16位寄存器AX(加载maxLung)比较:
MOV AX, [maxLung] ; AX = 0xFFFF(即-1,16位) CMP EDI, EAX ; EAX会被零扩展为32位的0x0000FFFF,而非符号扩展为0xFFFFFFFF
此时,任何正的全0子序列长度(EDI为正的32位值)都会被判定为小于等于0x0000FFFF,导致maxLung无法被正确更新。
3. 寄存器使用冗余且易引发类型混淆
全程使用32位寄存器EDI作为计数器,但总比特数是16位WORD,计数器最大值不会超过16位范围,使用16位寄存器DI即可,避免32位与16位混合操作的错误。
修正后的汇编代码
XOR SI, SI ; current bit index(16位足够,匹配len的WORD类型) XOR DI, DI ; zero subsequence length counter(16位) MOV BX, [len] ; load total bit length into BX MOV [minLung], BX ; initialize minLung with maximum possible length MOV CX, -1 ; load -1 into CX(16位,匹配maxLung的short类型) MOV [maxLung], CX ; initialize maxLung with -1 loop_start: CMP SI, [len] ; compare bit index with length(均为16位,无类型问题) JGE end_loop ; if index >= length, jump to end_loop MOV AX, SI ; load current bit index into AX(16位) MOV DX, AX ; copy current bit index into DX AND DX, 7 ; bit position within the byte (0...7) SHR AX, 3 ; byte number containing the bit MOV AL, [vet + AX] ; load current byte MOV CL, DL ; CL holds current bit position (0-7) SHR AL, CL ; shift to get the target bit AND AL, 1 ; isolate the current bit CMP AL, 0 ; check if bit == 0 JNE update_stats ; if bit == 1, jump to update_stats INC DI ; increment zero counter INC SI ; move to next bit JMP loop_start update_stats: CMP DI, 0 ; check if no zero subsequence before this 1 JE after_update ; Update minLung MOV AX, [minLung] CMP DI, AX JGE skip_min_update MOV [minLung], DI skip_min_update: ; Update maxLung(全程用16位寄存器,避免符号扩展错误) MOV AX, [maxLung] CMP DI, AX JLE skip_max_update MOV [maxLung], DI skip_max_update: XOR DI, DI ; reset zero counter after_update: INC SI JMP loop_start end_loop: CMP DI, 0 ; check if there's an unfinished zero subsequence JE check_result ; Update minLung for the last zero subsequence MOV AX, [minLung] CMP DI, AX JGE skip_end_min MOV [minLung], DI skip_end_min: ; Update maxLung for the last zero subsequence MOV AX, [maxLung] CMP DI, AX JLE skip_end_max MOV [maxLung], DI skip_end_max: check_result: MOV AX, [maxLung] CMP AX, -1 JNE done ; No zero subsequences, set both to -1 MOV AX, -1 MOV [minLung], AX MOV [maxLung], AX done:
内容的提问来源于stack exchange,提问作者Tania Volo
相关产品推荐
相关产品推荐

