⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 string.h

📁 linux0.11内核源代码
💻 H
📖 第 1 页 / 共 2 页
字号:
#ifndef _STRING_H_#define _STRING_H_#ifndef NULL#define NULL ((void *) 0)#endif#ifndef _SIZE_T#define _SIZE_Ttypedef unsigned int size_t;#endifextern char *strerror (int errno);/** This string-include defines all string functions as inline* functions. Use gcc. It also assumes ds=es=data space, this should be* normal. Most of the string-functions are rather heavily hand-optimized,* see especially strtok,strstr,str[c]spn. They should work, but are not* very easy to understand. Everything is done entirely within the register* set, making the functions fast and clean. String instructions have been* used through-out, making for "slightly" unclear code :-)** (C) 1991 Linus Torvalds*//** 这个字符串头文件以内嵌函数的形式定义了所有字符串操作函数。使用gcc 时,同时* 假定了ds=es=数据空间,这应该是常规的。绝大多数字符串函数都是经手工进行大量* 优化的,尤其是函数strtok、strstr、str[c]spn。它们应该能正常工作,但却不是那* 么容易理解。所有的操作基本上都是使用寄存器集来完成的,这使得函数即快有整洁。* 所有地方都使用了字符串指令,这又使得代码“稍微”难以理解?** (C) 1991 Linus Torvalds*///// 将一个字符串(src)拷贝到另一个字符串(dest),直到遇到NULL 字符后停止。// 参数:dest - 目的字符串指针,src - 源字符串指针。// %0 - esi(src),%1 - edi(dest)。extern inline char *strcpy (char *dest, const char *src){  __asm__ ("cld\n"		// 清方向位。	   "1:\tlodsb\n\t"	// 加载DS:[esi]处1 字节??al,并更新esi。	   "stosb\n\t"		// 存储字节al??ES:[edi],并更新edi。	   "testb %%al,%%al\n\t"	// 刚存储的字节是0?	   "jne 1b"		// 不是则向后跳转到标号1 处,否则结束。::"S" (src), "D" (dest):"si", "di", "ax");  return dest;			// 返回目的字符串指针。}//// 拷贝源字符串count 个字节到目的字符串。// 如果源串长度小于count 个字节,就附加空字符(NULL)到目的字符串。// 参数:dest - 目的字符串指针,src - 源字符串指针,count - 拷贝字节数。// %0 - esi(src),%1 - edi(dest),%2 - ecx(count)。extern inline char *strncpy (char *dest, const char *src, int count){  __asm__ ("cld\n"		// 清方向位。	   "1:\tdecl %2\n\t"	// 寄存器ecx--(count--)。	   "js 2f\n\t"		// 如果count<0 则向前跳转到标号2,结束。	   "lodsb\n\t"		// 取ds:[esi]处1 字节??al,并且esi++。	   "stosb\n\t"		// 存储该字节??es:[edi],并且edi++。	   "testb %%al,%%al\n\t"	// 该字节是0?	   "jne 1b\n\t"		// 不是,则向前跳转到标号1 处继续拷贝。	   "rep\n\t"		// 否则,在目的串中存放剩余个数的空字符。"stosb\n" "2:"::"S" (src), "D" (dest), "c" (count):"si", "di", "ax",	   "cx");  return dest;			// 返回目的字符串指针。}//// 将源字符串拷贝到目的字符串的末尾处。// 参数:dest - 目的字符串指针,src - 源字符串指针。// %0 - esi(src),%1 - edi(dest),%2 - eax(0),%3 - ecx(-1)。extern inline char *strcat (char *dest, const char *src){  __asm__ ("cld\n\t"		// 清方向位。	   "repne\n\t"		// 比较al 与es:[edi]字节,并更新edi++,	   "scasb\n\t"		// 直到找到目的串中是0 的字节,此时edi 已经指向后1 字节。	   "decl %1\n"		// 让es:[edi]指向0 值字节。	   "1:\tlodsb\n\t"	// 取源字符串字节ds:[esi]??al,并esi++。	   "stosb\n\t"		// 将该字节存到es:[edi],并edi++。	   "testb %%al,%%al\n\t"	// 该字节是0?	   "jne 1b"		// 不是,则向后跳转到标号1 处继续拷贝,否则结束。::"S" (src), "D" (dest), "a" (0), "c" (0xffffffff):"si", "di", "ax",	   "cx");  return dest;			// 返回目的字符串指针。}//// 将源字符串的count 个字节复制到目的字符串的末尾处,最后添一空字符。// 参数:dest - 目的字符串,src - 源字符串,count - 欲复制的字节数。// %0 - esi(src),%1 - edi(dest),%2 - eax(0),%3 - ecx(-1),%4 - (count)。extern inline char *strncat (char *dest, const char *src, int count){  __asm__ ("cld\n\t"		// 清方向位。	   "repne\n\t"		// 比较al 与es:[edi]字节,edi++。	   "scasb\n\t"		// 直到找到目的串的末端0 值字节。	   "decl %1\n\t"	// edi 指向该0 值字节。	   "movl %4,%3\n"	// 欲复制字节数??ecx。	   "1:\tdecl %3\n\t"	// ecx--(从0 开始计数)。	   "js 2f\n\t"		// ecx <0 ?,是则向前跳转到标号2 处。	   "lodsb\n\t"		// 否则取ds:[esi]处的字节??al,esi++。	   "stosb\n\t"		// 存储到es:[edi]处,edi++。	   "testb %%al,%%al\n\t"	// 该字节值为0?	   "jne 1b\n"		// 不是则向后跳转到标号1 处,继续复制。	   "2:\txorl %2,%2\n\t"	// 将al 清零。	   "stosb"		// 存到es:[edi]处。::"S" (src), "D" (dest), "a" (0), "c" (0xffffffff), "g" (count):"si", "di", "ax",	   "cx");  return dest;			// 返回目的字符串指针。}//// 将一个字符串与另一个字符串进行比较。// 参数:cs - 字符串1,ct - 字符串2。// %0 - eax(__res)返回值,%1 - edi(cs)字符串1 指针,%2 - esi(ct)字符串2 指针。// 返回:如果串1 > 串2,则返回1;串1 = 串2,则返回0;串1 < 串2,则返回-1。extern inline intstrcmp (const char *cs, const char *ct){  register int __res __asm__ ("ax");	// __res 是寄存器变量(eax)。  __asm__ ("cld\n"		// 清方向位。	   "1:\tlodsb\n\t"	// 取字符串2 的字节ds:[esi]??al,并且esi++。	   "scasb\n\t"		// al 与字符串1 的字节es:[edi]作比较,并且edi++。	   "jne 2f\n\t"		// 如果不相等,则向前跳转到标号2。	   "testb %%al,%%al\n\t"	// 该字节是0 值字节吗(字符串结尾)?	   "jne 1b\n\t"		// 不是,则向后跳转到标号1,继续比较。	   "xorl %%eax,%%eax\n\t"	// 是,则返回值eax 清零,	   "jmp 3f\n"		// 向前跳转到标号3,结束。	   "2:\tmovl $1,%%eax\n\t"	// eax 中置1。	   "jl 3f\n\t"		// 若前面比较中串2 字符<串1 字符,则返回正值,结束。	   "negl %%eax\n"	// 否则eax = -eax,返回负值,结束。"3:": "=a" (__res): "D" (cs), "S" (ct):"si", "di");  return __res;			// 返回比较结果。}//// 字符串1 与字符串2 的前count 个字符进行比较。// 参数:cs - 字符串1,ct - 字符串2,count - 比较的字符数。// %0 - eax(__res)返回值,%1 - edi(cs)串1 指针,%2 - esi(ct)串2 指针,%3 - ecx(count)。// 返回:如果串1 > 串2,则返回1;串1 = 串2,则返回0;串1 < 串2,则返回-1。extern inline intstrncmp (const char *cs, const char *ct, int count){  register int __res __asm__ ("ax");	// __res 是寄存器变量(eax)。  __asm__ ("cld\n"		// 清方向位。	   "1:\tdecl %3\n\t"	// count--。	   "js 2f\n\t"		// 如果count<0,则向前跳转到标号2。	   "lodsb\n\t"		// 取串2 的字符ds:[esi]??al,并且esi++。	   "scasb\n\t"		// 比较al 与串1 的字符es:[edi],并且edi++。	   "jne 3f\n\t"		// 如果不相等,则向前跳转到标号3。	   "testb %%al,%%al\n\t"	// 该字符是NULL 字符吗?	   "jne 1b\n"		// 不是,则向后跳转到标号1,继续比较。	   "2:\txorl %%eax,%%eax\n\t"	// 是NULL 字符,则eax 清零(返回值)。	   "jmp 4f\n"		// 向前跳转到标号4,结束。	   "3:\tmovl $1,%%eax\n\t"	// eax 中置1。	   "jl 4f\n\t"		// 如果前面比较中串2 字符<串2 字符,则返回1,结束。	   "negl %%eax\n"	// 否则eax = -eax,返回负值,结束。"4:": "=a" (__res): "D" (cs), "S" (ct), "c" (count):"si", "di",	   "cx");  return __res;			// 返回比较结果。}//// 在字符串中寻找第一个匹配的字符。// 参数:s - 字符串,c - 欲寻找的字符。// %0 - eax(__res),%1 - esi(字符串指针s),%2 - eax(字符c)。// 返回:返回字符串中第一次出现匹配字符的指针。若没有找到匹配的字符,则返回空指针。extern inline char *strchr (const char *s, char c){  register char *__res __asm__ ("ax");	// __res 是寄存器变量(eax)。  __asm__ ("cld\n\t"		// 清方向位。	   "movb %%al,%%ah\n"	// 将欲比较字符移到ah。	   "1:\tlodsb\n\t"	// 取字符串中字符ds:[esi]??al,并且esi++。	   "cmpb %%ah,%%al\n\t"	// 字符串中字符al 与指定字符ah 相比较。	   "je 2f\n\t"		// 若相等,则向前跳转到标号2 处。	   "testb %%al,%%al\n\t"	// al 中字符是NULL 字符吗?(字符串结尾?)	   "jne 1b\n\t"		// 若不是,则向后跳转到标号1,继续比较。	   "movl $1,%1\n"	// 是,则说明没有找到匹配字符,esi 置1。	   "2:\tmovl %1,%0\n\t"	// 将指向匹配字符后一个字节处的指针值放入eax	   "decl %0"		// 将指针调整为指向匹配的字符。: "=a" (__res): "S" (s), "" (c):"si");  return __res;			// 返回指针。}//// 寻找字符串中指定字符最后一次出现的地方。(反向搜索字符串)// 参数:s - 字符串,c - 欲寻找的字符。// %0 - edx(__res),%1 - edx(0),%2 - esi(字符串指针s),%3 - eax(字符c)。// 返回:返回字符串中最后一次出现匹配字符的指针。若没有找到匹配的字符,则返回空指针。extern inline char *strrchr (const char *s, char c){  register char *__res __asm__ ("dx");	// __res 是寄存器变量(edx)。  __asm__ ("cld\n\t"		// 清方向位。	   "movb %%al,%%ah\n"	// 将欲寻找的字符移到ah。	   "1:\tlodsb\n\t"	// 取字符串中字符ds:[esi]??al,并且esi++。	   "cmpb %%ah,%%al\n\t"	// 字符串中字符al 与指定字符ah 作比较。	   "jne 2f\n\t"		// 若不相等,则向前跳转到标号2 处。	   "movl %%esi,%0\n\t"	// 将字符指针保存到edx 中。	   "decl %0\n"		// 指针后退一位,指向字符串中匹配字符处。	   "2:\ttestb %%al,%%al\n\t"	// 比较的字符是0 吗(到字符串尾)?	   "jne 1b"		// 不是则向后跳转到标号1 处,继续比较。: "=d" (__res): "" (0), "S" (s), "a" (c):"ax", "si");  return __res;			// 返回指针。}//// 在字符串1 中寻找第1 个字符序列,该字符序列中的任何字符都包含在字符串2 中。// 参数:cs - 字符串1 指针,ct - 字符串2 指针。// %0 - esi(__res),%1 - eax(0),%2 - ecx(-1),%3 - esi(串1 指针cs),%4 - (串2 指针ct)。// 返回字符串1 中包含字符串2 中任何字符的首个字符序列的长度值。extern inline intstrspn (const char *cs, const char *ct){  register char *__res __asm__ ("si");	// __res 是寄存器变量(esi)。  __asm__ ("cld\n\t"		// 清方向位。	   "movl %4,%%edi\n\t"	// 首先计算串2 的长度。串2 指针放入edi 中。	   "repne\n\t"		// 比较al(0)与串2 中的字符(es:[edi]),并edi++。	   "scasb\n\t"		// 如果不相等就继续比较(ecx 逐步递减)。	   "notl %%ecx\n\t"	// ecx 中每位取反。	   "decl %%ecx\n\t"	// ecx--,得串2 的长度值。	   "movl %%ecx,%%edx\n"	// 将串2 的长度值暂放入edx 中。	   "1:\tlodsb\n\t"	// 取串1 字符ds:[esi]??al,并且esi++。	   "testb %%al,%%al\n\t"	// 该字符等于0 值吗(串1 结尾)?	   "je 2f\n\t"		// 如果是,则向前跳转到标号2 处。	   "movl %4,%%edi\n\t"	// 取串2 头指针放入edi 中。	   "movl %%edx,%%ecx\n\t"	// 再将串2 的长度值放入ecx 中。	   "repne\n\t"		// 比较al 与串2 中字符es:[edi],并且edi++。	   "scasb\n\t"		// 如果不相等就继续比较。	   "je 1b\n"		// 如果相等,则向后跳转到标号1 处。	   "2:\tdecl %0"	// esi--,指向最后一个包含在串2 中的字符。: "=S" (__res): "a" (0), "c" (0xffffffff), "" (cs), "g" (ct):"ax", "cx", "dx",	   "di");  return __res - cs;		// 返回字符序列的长度值。}//// 寻找字符串1 中不包含字符串2 中任何字符的首个字符序列。// 参数:cs - 字符串1 指针,ct - 字符串2 指针。// %0 - esi(__res),%1 - eax(0),%2 - ecx(-1),%3 - esi(串1 指针cs),%4 - (串2 指针ct)。// 返回字符串1 中不包含字符串2 中任何字符的首个字符序列的长度值。extern inline intstrcspn (const char *cs, const char *ct){  register char *__res __asm__ ("si");	// __res 是寄存器变量(esi)。  __asm__ ("cld\n\t"		// 清方向位。	   "movl %4,%%edi\n\t"	// 首先计算串2 的长度。串2 指针放入edi 中。	   "repne\n\t"		// 比较al(0)与串2 中的字符(es:[edi]),并edi++。	   "scasb\n\t"		// 如果不相等就继续比较(ecx 逐步递减)。	   "notl %%ecx\n\t"	// ecx 中每位取反。	   "decl %%ecx\n\t"	// ecx--,得串2 的长度值。	   "movl %%ecx,%%edx\n"	// 将串2 的长度值暂放入edx 中。	   "1:\tlodsb\n\t"	// 取串1 字符ds:[esi]??al,并且esi++。	   "testb %%al,%%al\n\t"	// 该字符等于0 值吗(串1 结尾)?	   "je 2f\n\t"		// 如果是,则向前跳转到标号2 处。	   "movl %4,%%edi\n\t"	// 取串2 头指针放入edi 中。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -