Linux中比较两个字符串的前count个字符的汇编实现
比较两个字符串的前 count
个字符strncmp
static inline int strncmp(const char * cs,const char * ct,size_t count)
{
register int __res;
int d0, d1, d2;
__asm__ __volatile__("1:\tdecl %3\n\t""js 2f\n\t""lodsb\n\t""scasb\n\t""jne 3f\n\t""testb %%al,%%al\n\t""jne 1b\n""2:\txorl %%eax,%%eax\n\t""jmp 4f\n""3:\tsbbl %%eax,%%eax\n\t""orb $1,%%al\n""4:":"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2):"1" (cs),"2" (ct),"3" (count));
return __res;
}
1. 函数功能概述
这是一个用内联汇编实现的 strncmp
函数,用于比较两个字符串的前 count
个字符
2. 代码分段详解
2.1. 第一段:函数声明和变量定义
static inline int strncmp(const char * cs,const char * ct,size_t count)
{register int __res;int d0, d1, d2;
static inline
表示内联函数,调用时直接展开const char * cs
第一个字符串指针const char * ct
第二个字符串指针size_t count
要比较的最大字符数register int __res
寄存器变量存储比较结果d0, d1, d2
临时变量用于汇编约束
2.2. 第二段:内联汇编开始和循环控制
__asm__ __volatile__("1:\tdecl %3\n\t""js 2f\n\t"
__asm__ __volatile__
开始内联汇编块1:\tdecl %3
标签1:递减计数器count
(操作数3)js 2f
如果结果为负(符号位为1),跳转到标签2(count减到-1表示比较完成)
2.3. 第三段:字符加载和比较
"lodsb\n\t""scasb\n\t"
lodsb
从[esi]
加载字节到al
,同时esi
加1(加载cs
的字符)scasb
比较al
与[edi]
的字节,同时edi
加1(比较ct
的字符)
2.4. 第四段:字符比较结果判断
"jne 3f\n\t""testb %%al,%%al\n\t""jne 1b\n"
jne 3f
如果字符不相等,跳转到标签3testb %%al,%%al
测试当前字符是否为0(字符串结束符)jne 1b
如果不是0,跳转回标签1继续循环
2.5. 第五段:字符串相等的情况
"2:\txorl %%eax,%%eax\n\t""jmp 4f\n"
2:\txorl %%eax,%%eax
标签2:将eax
清零(返回0,表示字符串相等)jmp 4f
跳转到标签4(函数结束)
2.6. 第六段:字符串不相等的情况
"3:\tsbbl %%eax,%%eax\n\t""orb $1,%%al\n""4:"
3:\tsbbl %%eax,%%eax
标签3:带借位减法,eax = eax - eax - CF
- 如果
cs
的字符 <ct
的字符,CF=1,结果为 -1 (0xFFFFFFFF) - 如果
cs
的字符 >ct
的字符,CF=0,结果为 0
- 如果
orb $1,%%al
将al
的最低位置1- 如果原来是 -1 (0xFF),置1后还是 -1 (0xFF)
- 如果原来是 0,置1后变成 1
4:
标签4:函数结束标签
2.7. 第七段:汇编约束条件
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2):"1" (cs),"2" (ct),"3" (count));
输出操作数:
"=a" (__res)
:__res
绑定到eax
寄存器(结果值)"=&S" (d0)
:d0
绑定到esi
寄存器(& 表示早期破坏)"=&D" (d1)
:d1
绑定到edi
寄存器"=&c" (d2)
:d2
绑定到ecx
寄存器
输入操作数:
"1" (cs)
:cs
使用与操作数1相同的约束(esi
)"2" (ct)
:ct
使用与操作数2相同的约束(edi
)"3" (count)
:count
使用与操作数3相同的约束(ecx
)
2.8. 第八段:函数返回
return __res;
}
- 返回比较结果
3. 函数工作流程图
寄存器使用说明
寄存器 | 用途 |
---|---|
eax | 存储当前字符和最终结果 |
esi | 源字符串 cs 指针 |
edi | 目标字符串 ct 指针 |
ecx | 计数器 count |
4. 汇编指令详解
decl
:递减操作数js
:符号标志为1时跳转(结果为负)lodsb
:从[esi]
加载字节到al
,esi++
scasb
:比较al
与[edi]
,设置标志位,edi++
jne
:不相等时跳转testb
:测试字节值xorl
:异或操作(用于清零)sbbl
:带借位减法orb
:或操作(用于置位)
5. 返回值说明
返回值 | 含义 |
---|---|
0 | 两个字符串在比较范围内完全相同 |
-1 | cs 字符串小于 ct 字符串 |
1 | cs 字符串大于 ct 字符串 |
6.比较逻辑
- 逐字符比较:每次比较一个字符对
- 三种终止条件:
- 达到
count
限制(所有字符都相等) - 遇到不相等的字符
- 遇到字符串结束符
\0
- 达到
- 结果计算:
- 完全相等:返回 0
- 不相等:根据字符的ASCII值差返回 -1 或 1
7. 函数功能总结
主要功能:比较两个字符串的前 count
个字符。
特点:
- 使用内联汇编实现,效率极高
- 正确处理字符串结束符和比较长度限制
- 使用标准的字符串比较返回值约定
- 利用 x86 字符串操作指令优化性能
这个实现充分展示了如何用汇编语言高效实现字符串操作,特别适合在内核等性能关键的场景中使用