Linux中比较两个字符串的前count个字符的汇编实现

比较两个字符串的前 count 个字符strncmp

c 复制代码
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. 第一段:函数声明和变量定义

c 复制代码
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. 第二段:内联汇编开始和循环控制

c 复制代码
    __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. 第三段:字符加载和比较

c 复制代码
        "lodsb\n\t"
        "scasb\n\t"
  • lodsb[esi] 加载字节到 al,同时 esi 加1(加载 cs 的字符)
  • scasb 比较 al[edi] 的字节,同时 edi 加1(比较 ct 的字符)

2.4. 第四段:字符比较结果判断

c 复制代码
        "jne 3f\n\t"
        "testb %%al,%%al\n\t"
        "jne 1b\n"
  • jne 3f 如果字符不相等,跳转到标签3
  • testb %%al,%%al 测试当前字符是否为0(字符串结束符)
  • jne 1b 如果不是0,跳转回标签1继续循环

2.5. 第五段:字符串相等的情况

c 复制代码
        "2:\txorl %%eax,%%eax\n\t"
        "jmp 4f\n"
  • 2:\txorl %%eax,%%eax 标签2:将 eax 清零(返回0,表示字符串相等)
  • jmp 4f 跳转到标签4(函数结束)

2.6. 第六段:字符串不相等的情况

c 复制代码
        "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,%%alal 的最低位置1
    • 如果原来是 -1 (0xFF),置1后还是 -1 (0xFF)
    • 如果原来是 0,置1后变成 1
  • 4: 标签4:函数结束标签

2.7. 第七段:汇编约束条件

c 复制代码
                     :"=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. 第八段:函数返回

c 复制代码
    return __res;
}
  • 返回比较结果

3. 函数工作流程图

是 否 不相等 相等 是0 不是0 开始strncmp count递减 count < 0? 设置eax=0
字符串相等 lodsb加载cs字符
scasb比较ct字符 字符相等? 根据CF标志设置返回值
字符为0?
字符串结束? 返回0 返回-1或1

寄存器使用说明

寄存器 用途
eax 存储当前字符和最终结果
esi 源字符串 cs 指针
edi 目标字符串 ct 指针
ecx 计数器 count

4. 汇编指令详解

  • decl:递减操作数
  • js:符号标志为1时跳转(结果为负)
  • lodsb:从 [esi] 加载字节到 alesi++
  • scasb:比较 al[edi],设置标志位,edi++
  • jne:不相等时跳转
  • testb:测试字节值
  • xorl:异或操作(用于清零)
  • sbbl:带借位减法
  • orb:或操作(用于置位)

5. 返回值说明

返回值 含义
0 两个字符串在比较范围内完全相同
-1 cs 字符串小于 ct 字符串
1 cs 字符串大于 ct 字符串

6.比较逻辑

  1. 逐字符比较:每次比较一个字符对
  2. 三种终止条件
    • 达到 count 限制(所有字符都相等)
    • 遇到不相等的字符
    • 遇到字符串结束符 \0
  3. 结果计算
    • 完全相等:返回 0
    • 不相等:根据字符的ASCII值差返回 -1 或 1

7. 函数功能总结

主要功能 :比较两个字符串的前 count 个字符。

特点

  • 使用内联汇编实现,效率极高
  • 正确处理字符串结束符和比较长度限制
  • 使用标准的字符串比较返回值约定
  • 利用 x86 字符串操作指令优化性能

这个实现充分展示了如何用汇编语言高效实现字符串操作,特别适合在内核等性能关键的场景中使用

相关推荐
文火冰糖的硅基工坊9 小时前
[嵌入式系统-115]:鸿蒙操作系统(HarmonyOS)与欧拉操作系统(openEuler)、Linux操作系统的关系、比较及异同如下:
linux·服务器·科技·华为·重构·架构·harmonyos
2401_837088509 小时前
Redis的vim基本操作
linux·编辑器·vim
馨谙9 小时前
标题:Linux 系统中的“保险库管理员”:深入浅出理解 /etc/shadow 文件
linux·运维·服务器
---学无止境---9 小时前
Linux中zonelist分配策略初始化
linux
撬动未来的支点10 小时前
【Linux内核】Linux系统启动之旅
linux
乌萨奇也要立志学C++11 小时前
【Linux】基础IO(一)Linux 文件操作从入门到实践:系统调用、文件描述符、重定向,为自定义Shell添加重定向
linux·运维·chrome
liujing1023292915 小时前
stm32大项目阶段20251015
linux
嵌入式郑工16 小时前
LINUX驱动开发: 设备和驱动是怎么匹配的?
linux·运维·服务器
郭式云源生法则17 小时前
归档及压缩、重定向与管道操作和综合使用,find精确查找、find处理查找结果、vim高级使用、vimdiff多文件使用
linux·运维·服务器