strchr()函数实现问题:汇编重写触发0x0段错误及调试困惑
修复strchr实现中的段错误与逻辑问题
我来帮你排查一下这个strchr实现里的问题,你碰到的段错误和逻辑bug主要有两处:
1. 未初始化的rcx导致非法内存访问
在good标签的代码里,你写了mov rax, [rdi + rcx],但整个程序里从来没有给rcx赋过值!rcx的初始值是随机的垃圾值,这会导致你去访问一个完全不确定的内存地址,大概率触发段错误(尤其是当这个随机地址指向0x0附近时)。
实际上你一直在用rax记录当前遍历的偏移量,所以这里应该用rax来计算目标地址,改成lea rax, [rdi + rax](直接用lea指令计算地址,比mov+add更高效)就对了。
2. 查找\0的逻辑顺序错误
strchr的标准语义是:如果要查找的字符是\0,需要返回字符串末尾那个\0的地址。但你的代码里先判断当前字符是否为0,一旦是就跳去end返回空指针,之后才判断要找的字符是不是0——这就导致当用户传入要找的字符是\0时,你直接返回了空指针,完全不符合预期。
正确的顺序应该是:先判断当前字符是否匹配目标字符(包括目标字符是\0的情况),再判断是否到了字符串末尾。
修正后的完整代码
.section .text global strchr strchr: xor rax, rax ; 初始化遍历偏移量为0 loop: mov cl, BYTE [rdi + rax] ; 读取当前字符到cl,避免重复访问内存 cmp cl, sil ; 比较当前字符与目标字符sil jz good ; 匹配成功,跳转到返回地址的逻辑 cmp cl, 0 ; 未匹配,判断是否到字符串末尾 jz end ; 到末尾且未找到,返回空指针 inc rax ; 偏移量+1,继续下一次循环 jmp loop good: lea rax, [rdi + rax] ; 计算目标字符的地址:起始地址+偏移量 ret end: xor rax, rax ; 返回空指针(比mov rax,0更高效) ret
额外优化说明
- 把当前字符先读到
cl里,避免了原代码中两次访问[rdi+rax]的重复内存操作,提升了效率 - 用
xor rax, rax代替mov rax, 0,是汇编里的常用小技巧,指令长度更短,执行效率更高 - 调整了判断顺序,完美符合strchr的标准行为:无论目标字符是普通字符还是
\0,都能正确返回对应的地址
内容的提问来源于stack exchange,提问作者C.Edelweiss
相关产品推荐
相关产品推荐

