汇编字符串函数Bug排查:最长连续相同字符统计结果异常
问题分析与修复
我一眼就看出问题出在你处理字符的方式上——你错误地用32位寄存器操作来处理8位的char类型数据,这直接导致了连续字符计数的逻辑错误。具体来说有这几个关键问题:
- 空字符串检查逻辑错误:你用
cmp [ebx], 0判断字符串是否为空,但32位汇编里[ebx]会读取4字节数据,而不是单个字符。正确的做法应该是检查单个字节是否为\0,也就是cmp byte ptr [ebx], 0。 - 字符存储与比较的位数不匹配:你用32位的
edx寄存器存当前字符,但char是8位类型。执行mov edx, [ebx]时会读取从ebx开始的4字节数据,后续的cmp [ebx], edx也是比较4字节内容。比如处理"aaaaa"时,第三个字符开始的4字节包含了末尾的\0,和之前的4个a不相等,就会错误中断连续计数,最终得到错误的结果2。
修复后的代码
我们把所有字符操作改为8位,用dl(edx的低8位寄存器)存储当前字符,所有涉及字符读取和比较的地方都加上byte ptr限定符:
#include <stdio.h> unsigned long najdlhsia(const char *vstup) { __asm { mov eax, 0 ; 存储最长连续长度,初始为0 mov ecx, 0 ; 存储当前连续长度,初始为0 mov ebx, vstup ; ebx指向字符串起始地址 cmp byte ptr [ebx], 0 ; 检查是否为空字符串 je k ; 空字符串直接返回0 mov dl, byte ptr [ebx] ; 读取第一个字符到8位寄存器dl add ebx, 1 inc eax ; 初始最长长度设为1 inc ecx ; 初始当前连续长度设为1 c: cmp byte ptr [ebx], 0 ; 检查是否到字符串末尾 je p ; 到末尾进入最后一次长度比较 cmp byte ptr [ebx], dl ; 比较当前字符与上一个字符(均为8位) jne a1 ; 字符不相等则更新最长长度 inc ecx ; 字符相等,当前连续长度+1 add ebx, 1 jmp c ; 继续循环 a1: cmp ecx, eax jng a2 ; 当前长度不大于最长长度则跳过更新 mov eax, ecx ; 更新最长长度为当前长度 a2: mov ecx, 1 ; 重置当前连续长度为1 mov dl, byte ptr [ebx] ; 读取新的字符 add ebx, 1 jmp c p: cmp ecx, eax jng k ; 最后一次比较,更新最长长度 mov eax, ecx k: } } int main() { printf("%lu\n", najdlhsia("aaaaa")); // 输出5 printf("%lu\n", najdlhsia("aabbbcaaaabbccc")); // 输出4 printf("%lu\n", najdlhsia("")); // 输出0 return 0; }
关键修改说明
- 所有字符读取操作改为
mov dl, byte ptr [ebx],只读取单个8位字符; - 字符比较操作改为
cmp byte ptr [ebx], dl,确保只比较单个字符; - 修正空字符串检查逻辑为
cmp byte ptr [ebx], 0; main中用%lu格式符输出,匹配unsigned long的返回类型,避免格式不匹配问题。
现在运行代码,"aaaaa"会正确返回5,其他测试用例也能得到预期结果。
内容的提问来源于stack exchange,提问作者Jozko
相关产品推荐
相关产品推荐

