Linux中在字符串中查找指定字符的第一次出现位置的汇编实现
在字符串中查找指定字符的第一次出现位置strchr
static inline char * strchr(const char * s, int c)
{
int d0;
register char * __res;
__asm__ __volatile__("movb %%al,%%ah\n""1:\tlodsb\n\t""cmpb %%ah,%%al\n\t""je 2f\n\t""testb %%al,%%al\n\t""jne 1b\n\t""movl $1,%1\n""2:\tmovl %1,%0\n\t""decl %0":"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
return __res;
}
1. 函数功能概述
这是一个用内联汇编实现的 strchr
函数,用于在字符串中查找指定字符的第一次出现位置
2. 代码分段详解
2.1. 第一段:函数声明和变量定义
static inline char *strchr(const char *s, int c)
{int d0;register char *__res;
static inline
表示这是内联函数,调用时直接展开而不是函数调用const char *s
是输入字符串指针int c
是要查找的字符int d0
用于存储临时值(在汇编中作为占位符)register char *__res
声明寄存器变量,用于存储结果指针
2.2. 第二段:内联汇编开始和初始设置
__asm__ __volatile__("movb %%al,%%ah\n\t"
__asm__ __volatile__
开始内联汇编块,volatile
表示禁止编译器优化movb %%al,%%ah
将字符c
(在al
寄存器中)复制到ah
寄存器中备份%%al
对应参数c
(通过约束条件 “0” 传入)- 备份是因为
lodsb
指令会修改al
寄存器
2.2. 第三段:字符串扫描循环
"1:\tlodsb\n\t""cmpb %%ah,%%al\n\t""je 2f\n\t""testb %%al,%%al\n\t""jne 1b\n\t"
1:\tlodsb
标签1:加载字符串字节到al
,同时递增esi
指针cmpb %%ah,%%al
比较当前字符(al
)与目标字符(ah
)je 2f
如果相等,跳转到标签2testb %%al,%%al
测试当前字符是否为0(字符串结束)jne 1b
如果不是0,跳转回标签1(向后跳转),继续循环
2.3. 第四段:处理查找失败情况
"movl $1,%1\n\t"
movl $1,%1
将1移动到操作数1(d0
变量)- 这行代码只在查找失败(到达字符串末尾未找到字符)时执行
2.4. 第五段:处理查找成功情况
"2:\tmovl %1,%0\n\t""decl %0"
2:\tmovl %1,%0
标签2:将操作数1(d0
或esi
)的值复制到操作数0(__res
)decl %0
递减结果指针(因为lodsb
在比较后自动递增了指针)
2.5. 第六段:汇编约束条件
: "=a" (__res), "=&S" (d0): "1" (s), "0" (c));
输出操作数:
"=a" (__res)
:__res
变量绑定到eax
寄存器(= 表示只写)"=&S" (d0)
:d0
变量绑定到esi
寄存器(& 表示早期破坏)
输入操作数:
"1" (s)
:输入字符串s
使用与操作数1相同的约束(即esi
寄存器)"0" (c)
:输入字符c
使用与操作数0相同的约束(即eax
寄存器)
2.6. 第七段:函数返回
return __res;
}
- 返回查找到的字符指针,如果未找到则返回 NULL
3. 函数工作流程图
4. 寄存器使用说明
寄存器 | 用途 |
---|---|
eax (al/ah) | al 存储当前字符,ah 存储目标字符 |
esi | 字符串扫描指针 |
__res | 结果指针(通过 eax 返回) |
5. 汇编指令详解
lodsb
:从[esi]
加载字节到al
,同时esi
自动加1cmpb
:比较两个字节testb
:测试字节值(常用于检测是否为0)je/jne
:条件跳转(相等/不相等)movb/movl
:移动字节/双字decl
:递减
6. 函数功能总结
主要功能:在字符串 s
中查找字符 c
的第一次出现位置
返回值:
- 成功:指向找到字符的指针
- 失败:NULL 指针
特点:
- 使用内联汇编实现,效率高
- 直接操作寄存器,避免函数调用开销
- 使用
lodsb
指令高效遍历字符串 - 正确处理字符串终止符检测
这个实现展示了如何用汇编语言高效实现字符串操作,特别适合在内核等性能敏感的场景中使用。