在字符串中查找指定字符的第一次出现位置strchr
c
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. 第一段:函数声明和变量定义
c
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. 第二段:内联汇编开始和初始设置
c
__asm__ __volatile__(
"movb %%al,%%ah\n\t"
__asm__ __volatile__
开始内联汇编块,volatile
表示禁止编译器优化movb %%al,%%ah
将字符c
(在al
寄存器中)复制到ah
寄存器中备份%%al
对应参数c
(通过约束条件 "0" 传入)- 备份是因为
lodsb
指令会修改al
寄存器
2.2. 第三段:字符串扫描循环
c
"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. 第四段:处理查找失败情况
c
"movl $1,%1\n\t"
movl $1,%1
将1移动到操作数1(d0
变量)- 这行代码只在查找失败(到达字符串末尾未找到字符)时执行
2.4. 第五段:处理查找成功情况
c
"2:\tmovl %1,%0\n\t"
"decl %0"
2:\tmovl %1,%0
标签2:将操作数1(d0
或esi
)的值复制到操作数0(__res
)decl %0
递减结果指针(因为lodsb
在比较后自动递增了指针)
2.5. 第六段:汇编约束条件
c
: "=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. 第七段:函数返回
c
return __res;
}
- 返回查找到的字符指针,如果未找到则返回 NULL
3. 函数工作流程图
相等 不相等 是0,字符串结束 不是0 开始strchr 备份字符c到ah lodsb加载字符到al 比较al和ah 跳转到成功处理 测试al是否为0 设置d0=1查找失败 继续循环 返回NULL 调整指针位置 返回找到的指针
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
指令高效遍历字符串 - 正确处理字符串终止符检测
这个实现展示了如何用汇编语言高效实现字符串操作,特别适合在内核等性能敏感的场景中使用。