简单实现posix中规定的memcmp函数
简介
memcmp函数的功能非常简单,传入两个指针s1和s2,以及要比较的字节大小n,比较这两块内存的值的差异(逐字节比较,把每个字节都翻译为unsigned char)。当比较第i位时,如果相等,则返回0, 否则返回不相等的字节的差值(s1[i]-s2[i]).
实现
这个问题,本来是可以无脑的写c代码来逐字节比较的。但是嘛,为了能够更高效的实现,咱们就手写汇编来做吧。
我们使用repe和cmpsb这两条指令来实现。
repz指令是一个循环指令,每次循环会不断的递减rcx寄存器内的值,当rcx为0或处理器的zero flag不为1时,退出循环。
cmpsb指令则是对两个字节作比较的指令,在计算结束后,会设置相应的状态标志位。cmpsb指令涉及到的两个操作数分别存在rdi、rsi寄存器中。在操作结束后,如果这两个操作数的值相同,则会将ZF置位。不管这两个操作数的值是否相同,都会将指针s1、s2自增1。(下面的代码已经将DF复位,因此指针是自增的)
首先,我们将处理器的zero flag给置位,假设这两块内存相等。然后把len传入rcx寄存器,一共循环len次。
然后我们使用repz;cmpsb,逐字节比较。每次比较之后,不管是否相同,s1、s2都会自增。
如果比较完所有的字节,都是相同的话,此时ZF=1. 而输出nz到diff中,因此输出的是0.
如果某一字节不相同,那么diff=1。再在下面计算这两个字节到底相差了多少,然后就出结果了。
static inline int memcmp(const void *s1, const void *s2, size_t len)
{
int diff;
asm("cld \n\t" // 复位DF,确保s1、s2指针是自增的
"repz; cmpsb\n\t" CC_SET(nz)
: CC_OUT(nz)(diff), "+D"(s1), "+S"(s2)
: "c"(len)
: "memory");
if (diff)
diff = *(const unsigned char *)(s1 - 1) - *(const unsigned char *)(s2 - 1);
return diff;
}
关于CC_SET和CC_OUT
可能有的小伙伴会对CC_SET和CC_OUT比较疑惑,这里将涉及的代码放出来:
CC_SET()和CC_OUT()
由于我们的编译器支持__GCC_ASM_FLAG_OUTPUTS__,因此CC_SET的工作是空的。
然后,CC_OUT就是把rflags的某一位给输出出来。上面的nz就是对ZF求反的意思。
相关链接
https://pubs.opengroup.org/onlinepubs/9699919799/functions/memcmp.html
转载请注明来源:https://longjin666.cn/?p=1572
相关文章
- 虚函数后面的分号可有可无_虚函数需要实现吗
- 【说站】php中实现数组去重的函数
- golang实现RSA2的签名与验签函数
- 基于Redis位图实现用户签到功能
- MySQL实现时间随机函数的简单方法(mysql时间随机函数)
- 利用Oracle的百分比函数实现数据的快速统计(oracle百分比函数)
- php实现文件与16进制相互转换详解编程语言
- 揭秘Oracle数据库的存储过程实现原理(oracle存储过程解密)
- Linux 重命名函数实现文件操作(linux重命名函数)
- oe使用 Linux 函数chmod实现文件权限管理(linuxc函数chm)
- Linux中实现共享内存的函数使用(linux共享内存函数)
- ntfs格式?Linux下如何实现NTFS分区挂载(linux中如何挂载)
- 深入Oracle:查看函数实现细节(oracle查看函数内容)
- 利用Oracle表函数实现数据处理(oracle表函数)
- Linux目录管理:实现最佳性能(目录项linux)
- SQL Server的精确除法实现(sqlserver的除法)
- MSSQL使用集合函数实现数据简单处理(mssql集合函数)
- 使用MySQL中的WEEK函数实现周数计算(mysql 中week)
- 利用Oracle全拼函数实现中文及音节拼音转换(oracle 全拼函数)
- Oracle实现月初函数简单操作轻松取值(oracle 写月初函数)
- 联通云Redis助力业务发展实现多维度应用场景(联通云redis应用场景)
- 使用Oracle中的格式化函数实现输出精确结果(oracle中输出格式)
- Redis集群模式搭配哨兵,实现高可用(redis集群模式配哨兵)
- Oracle F函数实现高效数据处理(oracle f 函数)
- 使用Oracle9 DECODE函数实现行转列(oracle9行转列函数)
- asp的分词实现代码
- asp代码实现检测组件是否安装的函数
- java获取当前函数名的实现代码
- js实现日期级联效果
- strcat函数实现简单示例
- JavaScript实现的in_array函数
- C#中事件的动态调用实现方法