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

📄 string.h

📁 LINUX 0.11版内核代码。 并有代码分析说明。
💻 H
📖 第 1 页 / 共 3 页
字号:
	   "notl %0\n\t"	// ecx 取反。
	   "decl %0"		// ecx--,得字符串得长度值。
: "=c" (__res): "D" (s), "a" (0), "" (0xffffffff):"di");
  return __res;			// 返回字符串长度值。
}*/
extern char *___strtok;		// 用于临时存放指向下面被分析字符串1(s)的指针。//// 利用字符串2 中的字符将字符串1 分割成标记(tokern)序列。// 将串1 看作是包含零个或多个单词(token)的序列,并由分割符字符串2 中的一个或多个字符分开。// 第一次调用strtok()时,将返回指向字符串1 中第1 个token 首字符的指针,并在返回token 时将// 一null 字符写到分割符处。后续使用null 作为字符串1 的调用,将用这种方法继续扫描字符串1,// 直到没有token 为止。在不同的调用过程中,分割符串2 可以不同。// 参数:s - 待处理的字符串1,ct - 包含各个分割符的字符串2。// 汇编输出:%0 - ebx(__res),%1 - esi(__strtok);// 汇编输入:%2 - ebx(__strtok),%3 - esi(字符串1 指针s),%4 - (字符串2 指针ct)。// 返回:返回字符串s 中第1 个token,如果没有找到token,则返回一个null 指针。// 后续使用字符串s 指针为null 的调用,将在原字符串s 中搜索下一个token。extern _inline char *strtok (char *s, register const char *ct){//  register char *__res;
	_asm {
		pushf
		mov esi,s
		test esi,esi	// 首先测试esi(字符串1 指针s)是否是NULL。
		jne l1		// 如果不是,则表明是首次调用本函数,跳转标号1。
		mov ebx,strtok
		test ebx,ebx	// 如果是NULL,则表示此次是后续调用,测ebx(__strtok)。
		je l8		// 如果ebx 指针是NULL,则不能处理,跳转结束。
		mov esi,ebx	// 将ebx 指针复制到esi。
	l1: xor ebx,ebx	// 清ebx 指针。
		mov edi,ct	// 下面求字符串2 的长度。edi 指向字符串2。
		mov ecx,0xffffffff 	// 置ecx = 0xffffffff。
		xor eax,eax	// 清零eax。
		cld
		repne scasb// 将al(0)与es:[edi]比较,并且edi++。直到找到字符串2 的结束null 字符,或计数ecx==0。
		not ecx	// 将ecx 取反,
		dec ecx	// ecx--,得到字符串2 的长度值。
		je l7	// 分割符字符串空 // 若串2 长度为0,则转标号7。
		mov edx,ecx	// 将串2 长度暂存入edx。
	l2: lodsb	// 取串1 的字符ds:[esi]->al,并且esi++。
		test al,al	// 该字符为0 值吗(串1 结束)?
		je l7		// 如果是,则跳转标号7。
		mov edi,ct	// edi 再次指向串2 首。
		mov ecx,edx	// 取串2 的长度值置入计数器ecx。
		repne scasb// 将al 中串1 的字符与串2 中所有字符比较,判断该字符是否为分割符。
		je l2		// 若能在串2 中找到相同字符(分割符),则跳转标号2。
		dec esi	// 若不是分割符,则串1 指针esi 指向此时的该字符。
		cmp [esi],0	// 该字符是NULL 字符吗?
		je l7		// 若是,则跳转标号7 处。
		mov ebx,esi	// 将该字符的指针esi 存放在ebx。
	l3: lodsb	// 取串1 下一个字符ds:[esi]->al,并且esi++。
		test al,al	// 该字符是NULL 字符吗?
		je l5		// 若是,表示串1 结束,跳转到标号5。
		mov edi,ct	// edi 再次指向串2 首。
		mov ecx,edx	// 串2 长度值置入计数器ecx。
		repne scasb // 将al 中串1 的字符与串2 中每个字符比较,测试al 字符是否是分割符。
		jne l3		// 若不是分割符则跳转标号3,检测串1 中下一个字符。
		dec esi	// 若是分割符,则esi--,指向该分割符字符。
		cmp [esi],0	// 该分割符是NULL 字符吗?
		je l5		// 若是,则跳转到标号5。
		mov [esi],0	// 若不是,则将该分割符用NULL 字符替换掉。
		inc esi	// esi 指向串1 中下一个字符,也即剩余串首。
		jmp l6		// 跳转标号6 处。
	l5: xor esi,esi	// esi 清零。
	l6: cmp [ebx],0	// ebx 指针指向NULL 字符吗?
		jne l7	// 若不是,则跳转标号7。
		xor ebx,ebx	// 若是,则让ebx=NULL。
	l7: test ebx,ebx	// ebx 指针为NULL 吗?
		jne l8	// 若不是则跳转8,结束汇编代码。
		mov esi,ebx	// 将esi 置为NULL。
//	l8: mov __res,esi
	l8: mov eax,esi
		popf
	}//  return __res;			// 返回指向新token 的指针。}/*extern _inline char *
strtok (char *s, const char *ct)
{
  register char *__res __asm__ ("si");
  __asm__ ("testl %1,%1\n\t"	// 首先测试esi(字符串1 指针s)是否是NULL。
	   "jne 1f\n\t"		// 如果不是,则表明是首次调用本函数,跳转标号1。
	   "testl %0,%0\n\t"	// 如果是NULL,则表示此次是后续调用,测ebx(__strtok)。
	   "je 8f\n\t"		// 如果ebx 指针是NULL,则不能处理,跳转结束。
	   "movl %0,%1\n"	// 将ebx 指针复制到esi。
	   "1:\txorl %0,%0\n\t"	// 清ebx 指针。
	   "movl $-1,%%ecx\n\t"	// 置ecx = 0xffffffff。
	   "xorl %%eax,%%eax\n\t"	// 清零eax。
	   "cld\n\t"		// 清方向位。
	   "movl %4,%%edi\n\t"	// 下面求字符串2 的长度。edi 指向字符串2。
	   "repne\n\t"		// 将al(0)与es:[edi]比较,并且edi++。
	   "scasb\n\t"		// 直到找到字符串2 的结束null 字符,或计数ecx==0。
	   "notl %%ecx\n\t"	// 将ecx 取反,
	   "decl %%ecx\n\t"	// ecx--,得到字符串2 的长度值。
	   "je 7f\n\t"		// empty delimeter-string 
// 分割符字符串空 // 若串2 长度为0,则转标号7。
	   "movl %%ecx,%%edx\n"	// 将串2 长度暂存入edx。
	   "2:\tlodsb\n\t"	// 取串1 的字符ds:[esi]??al,并且esi++。
	   "testb %%al,%%al\n\t"	// 该字符为0 值吗(串1 结束)?
	   "je 7f\n\t"		// 如果是,则跳转标号7。
	   "movl %4,%%edi\n\t"	// edi 再次指向串2 首。
	   "movl %%edx,%%ecx\n\t"	// 取串2 的长度值置入计数器ecx。
	   "repne\n\t"		// 将al 中串1 的字符与串2 中所有字符比较,
	   "scasb\n\t"		// 判断该字符是否为分割符。
	   "je 2b\n\t"		// 若能在串2 中找到相同字符(分割符),则跳转标号2。
	   "decl %1\n\t"	// 若不是分割符,则串1 指针esi 指向此时的该字符。
	   "cmpb $0,(%1)\n\t"	// 该字符是NULL 字符吗?
	   "je 7f\n\t"		// 若是,则跳转标号7 处。
	   "movl %1,%0\n"	// 将该字符的指针esi 存放在ebx。
	   "3:\tlodsb\n\t"	// 取串1 下一个字符ds:[esi]??al,并且esi++。
	   "testb %%al,%%al\n\t"	// 该字符是NULL 字符吗?
	   "je 5f\n\t"		// 若是,表示串1 结束,跳转到标号5。
	   "movl %4,%%edi\n\t"	// edi 再次指向串2 首。
	   "movl %%edx,%%ecx\n\t"	// 串2 长度值置入计数器ecx。
	   "repne\n\t"		// 将al 中串1 的字符与串2 中每个字符比较,
	   "scasb\n\t"		// 测试al 字符是否是分割符。
	   "jne 3b\n\t"		// 若不是分割符则跳转标号3,检测串1 中下一个字符。
	   "decl %1\n\t"	// 若是分割符,则esi--,指向该分割符字符。
	   "cmpb $0,(%1)\n\t"	// 该分割符是NULL 字符吗?
	   "je 5f\n\t"		// 若是,则跳转到标号5。
	   "movb $0,(%1)\n\t"	// 若不是,则将该分割符用NULL 字符替换掉。
	   "incl %1\n\t"	// esi 指向串1 中下一个字符,也即剩余串首。
	   "jmp 6f\n"		// 跳转标号6 处。
	   "5:\txorl %1,%1\n"	// esi 清零。
	   "6:\tcmpb $0,(%0)\n\t"	// ebx 指针指向NULL 字符吗?
	   "jne 7f\n\t"		// 若不是,则跳转标号7。
	   "xorl %0,%0\n"	// 若是,则让ebx=NULL。
	   "7:\ttestl %0,%0\n\t"	// ebx 指针为NULL 吗?
	   "jne 8f\n\t"		// 若不是则跳转8,结束汇编代码。
	   "movl %0,%1\n"	// 将esi 置为NULL。
"8:": "=b" (__res), "=S" (___strtok): "" (___strtok), "1" (s), "g" (ct):"ax", "cx", "dx",
	   "di");
  return __res;			// 返回指向新token 的指针。
}*/
//// 内存块复制。从源地址src 处开始复制n 个字节到目的地址dest 处。// 参数:dest - 复制的目的地址,src - 复制的源地址,n - 复制字节数。// %0 - ecx(n),%1 - esi(src),%2 - edi(dest)。extern _inline void *memcpy (void *dest, const void *src, int n){
	_asm{
		pushf
		mov esi,src
		mov edi,dest
		mov ecx,n
		cld		// 清方向位。
		rep movsb	// 重复执行复制ecx 个字节,从ds:[esi]到es:[edi],esi++,edi++。
		popf
	}	return dest;			// 返回目的地址。}/*extern _inline void *
memcpy (void *dest, const void *src, int n)
{
  __asm__ ("cld\n\t"		// 清方向位。
	   "rep\n\t"		// 重复执行复制ecx 个字节,
	   "movsb"		// 从ds:[esi]到es:[edi],esi++,edi++。
::"c" (n), "S" (src), "D" (dest):"cx", "si", "di");
  return dest;			// 返回目的地址。
}*/
//// 内存块移动。同内存块复制,但考虑移动的方向。// 参数:dest - 复制的目的地址,src - 复制的源地址,n - 复制字节数。// 若dest<src 则:%0 - ecx(n),%1 - esi(src),%2 - edi(dest)。// 否则:%0 - ecx(n),%1 - esi(src+n-1),%2 - edi(dest+n-1)。// 这样操作是为了防止在复制时错误地重叠覆盖。extern _inline void *memmove (void *dest, const void *src, int n){	if (dest < src) 
	{_asm {
		pushf
		mov esi,src
		mov edi,dest
		mov ecx,n
		cld		// 清方向位。
		rep movsb// 从ds:[esi]到es:[edi],并且esi++,edi++,重复执行复制ecx 字节。
		popf
	}}else{_asm {
		pushf//		mov esi,src + n - 1
		mov esi,src
		add esi,n - 1
//		mov edi,dest + n - 1
		mov edi,dest
		add edi,n - 1
		mov ecx,n
		std		// 置方向位,从末端开始复制。
		rep movsb// 从ds:[esi]到es:[edi],并且esi--,edi--,复制ecx 个字节。
		popf
	}}  return dest;}/*extern _inline void *
memmove (void *dest, const void *src, int n)
{
  if (dest < src)
    __asm__ ("cld\n\t"		// 清方向位。
	     "rep\n\t"		// 从ds:[esi]到es:[edi],并且esi++,edi++,
	     "movsb"		// 重复执行复制ecx 字节。
  ::"c" (n), "S" (src), "D" (dest):"cx", "si", "di");
  else
    __asm__ ("std\n\t"		// 置方向位,从末端开始复制。
	     "rep\n\t"		// 从ds:[esi]到es:[edi],并且esi--,edi--,
	     "movsb"		// 复制ecx 个字节。
  ::"c" (n), "S" (src + n - 1), "D" (dest + n - 1):"cx", "si",
	     "di");
  return dest;
}*/
//// 比较n 个字节的两块内存(两个字符串),即使遇上NULL 字节也不停止比较。// 参数:csrc - 内存块1 地址,ct - 内存块2 地址,count - 比较的字节数。// %0 - eax(__res),%1 - eax(0),%2 - edi(内存块1),%3 - esi(内存块2),%4 - ecx(count)。// 返回:若块1>块2 返回1;块1<块2,返回-1;块1==块2,则返回0。extern _inline intmemcmp (const void *csrc, const void *ct, int count){//  register int __res; //__asm__ ("ax")	 __res 是寄存器变量。
	_asm {
		pushf
		mov edi,csrc
		mov esi,ct
		xor eax,eax // eax = 0
		mov ecx,count
		cld		// 清方向位。
		repe cmpsb// 比较ds:[esi]与es:[edi]的内容,并且esi++,edi++。如果相等则重复,
		je l1		// 如果都相同,则跳转到标号1,返回0(eax)值
		mov eax,1	// 否则eax 置1,
		jl l1		// 若内存块2 内容的值<内存块1,则跳转标号1。
		neg eax	// 否则eax = -eax。
//	l1: mov __res,eax
	l1:	popf
	}//  return __res;			// 返回比较结果。}/*extern _inline int
memcmp (const void *csrc, const void *ct, int count)
{
  register int __res __asm__ ("ax");	// __res 是寄存器变量。
  __asm__ ("cld\n\t"		// 清方向位。
	   "repe\n\t"		// 如果相等则重复,
	   "cmpsb\n\t"		// 比较ds:[esi]与es:[edi]的内容,并且esi++,edi++。
	   "je 1f\n\t"		// 如果都相同,则跳转到标号1,返回0(eax)值
	   "movl $1,%%eax\n\t"	// 否则eax 置1,
	   "jl 1f\n\t"		// 若内存块2 内容的值<内存块1,则跳转标号1。
	   "negl %%eax\n"	// 否则eax = -eax。
"1:": "=a" (__res): "" (0), "D" (csrc), "S" (ct), "c" (count):"si", "di",
	   "cx");
  return __res;			// 返回比较结果。
}*/
//// 在n 字节大小的内存块(字符串)中寻找指定字符。// 参数:csrc - 指定内存块地址,c - 指定的字符,count - 内存块长度。// %0 - edi(__res),%1 - eax(字符c),%2 - edi(内存块地址csrc),%3 - ecx(字节数count)。// 返回第一个匹配字符的指针,如果没有找到,则返回NULL 字符。extern _inline void *memchr (const void *csrc, char c, int count){//  register void *__res;	// __res 是寄存器变量。  if (!count)			// 如果内存块长度==0,则返回NULL,没有找到。    return NULL;
	_asm {
		pushf
		mov edi,csrc
		mov ecx,count
		mov al,c
		cld		// 清方向位。
		repne scasb// al 中字符与es:[edi]字符作比较,并且edi++,如果不相等则重复执行下面语句,
		je l1		// 如果相等则向前跳转到标号1 处。
		mov edi,1	// 否则edi 中置1。
	l1: dec edi	// 让edi 指向找到的字符(或是NULL)。
//		mov __res,edi
		mov eax,edi
		popf
	}//  return __res;			// 返回字符指针。}/*extern _inline void *
memchr (const void *csrc, char c, int count)
{
  register void *__res __asm__ ("di");	// __res 是寄存器变量。
  if (!count)			// 如果内存块长度==0,则返回NULL,没有找到。
    return NULL;
  __asm__ ("cld\n\t"		// 清方向位。
	   "repne\n\t"		// 如果不相等则重复执行下面语句,
	   "scasb\n\t"		// al 中字符与es:[edi]字符作比较,并且edi++,
	   "je 1f\n\t"		// 如果相等则向前跳转到标号1 处。
	   "movl $1,%0\n"	// 否则edi 中置1。
	   "1:\tdecl %0"	// 让edi 指向找到的字符(或是NULL)。
: "=D" (__res): "a" (c), "D" (csrc), "c" (count):"cx");
  return __res;			// 返回字符指针。
}*/
//// 用字符填写指定长度内存块。// 用字符c 填写s 指向的内存区域,共填count 字节。// %0 - eax(字符c),%1 - edi(内存地址),%2 - ecx(字节数count)。extern _inline void *memset (void *s, char c, int count){
	_asm {
		pushf
		mov edi,s
		mov ecx,count
		mov al,c
		cld		// 清方向位。
		rep stosb// 将al 中字符存入es:[edi]中,并且edi++。重复ecx 指定的次数,执行
		popf
	}  return s;}/*extern _inline void *
memset (void *s, char c, int count)
{
  __asm__ ("cld\n\t"		// 清方向位。
	   "rep\n\t"		// 重复ecx 指定的次数,执行
	   "stosb"		// 将al 中字符存入es:[edi]中,并且edi++。
::"a" (c), "D" (s), "c" (count):"cx", "di");
  return s;
}*/
#endif

⌨️ 快捷键说明

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