概述
#ifndef _STRING_H
#define _STRING_H
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef unsigned int size_t;
#endif
extern char * strerror(int errno);
/*
*这个字符串头文件以内嵌函数的形式定义来所有字符串操作函数.使用gcc时,同时假定了ds=es=数据
*空间,这应该是常规的.大部分的字符串功能函数都是手工进行优化的,尤其是strtok,strstr,str[c]
*他们应该可以工作,但是不那么容易理解,所有的函数都是使用寄存器直接操作的,使得所有的功能都很
*快并且整洁.
*/
/*
*将一个字符串(src)拷贝到(dest),直到遇见NULL字符后停止
*参数:dest-目的字符串指针,src-源字符串指针
*%0-esi(src),%1-edi(dest)
*/
extern inline char* strcpy(char*dest,const char *src)
{
__asm__("cldn" //清方向位
"1:tlodsbnt" //加载DS:[esi]处1字节->al,并更新esi
"stosbnt" //存储字节al->ES:[edi],并更新edi
"testb %%al,%%alnt" //刚存储字节是不是0
"jne 1b" //不是0向后跳转1处,否则结束
:
:"S"(src),"D"(dest)
:"si","di","ax"
);
return dest;
}
/*
*拷贝源字符串count个字节到目的字符串,如果源串长度小于count,就附加空字符到目的字符串
*参数:dest-目的字符串指针,src-源字符串指针,count-拷贝字节数
*%0-esi(src),%1-edi(dest),%2-ecx(count)
*/
extern inline char* strncpy(char * dest,char *src,int count)
{
__asm__("cldn" //请方向位
"1:tdecl %2nt" //寄存器ecx--(count--)
"js 2fnt" //如果count<0跳转到2,结束
"lodsb nt" //取ds:[esi],->al,esi++
"stosbnt" //存储字节al->es:[edi],edi++
"testb %%al,%%alnt"//该自己是否为0
"jne 1bnt" //不是跳转到1,继续
"repnt" //否则在目的字符串中存放剩余个数的空字符
"stosbn" //
"2:" //
:
:"S"(src),"D"(dest),"c"(count)
:"si","di","ax","cx"
);
return dest;
}
/*
*将源字符串拷贝到目的字符串的末尾处
*参数:dest-目的字符串指针,src源字符串指针-,
*%0-esi(sec),%1-edi(dest),%2-eax(0),%3-ecx(0xffffffff)
*/
extern inline char * strcat(char* dest,const char* src)
{
__asm__("cldnt" // 清方向位,
"repnent" //比较al与es:[edi]字节,edi++
"scasbnt" //直到找到目的串中是0的字节,此时edi已指向后1字节
"decl %1n" //额昂edi指向0值字节
"1:t lodsbnt"//取源字符串ds:[esi]->al,esi++
"stosbnt" //存储al->ds:[edi],edi++
"testb %%al,%%alnt" //该字节是否为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(0xffffffff),%4-(count)
*/
extern inline char* strncat(char* dest,const char*src,int count)
{
__asm__("cldnt" //清方向位
"repnent" //比较al和es:[edi]字节,edi++
"scasb nt" //直到找到目的串的末端0值字节
"decl %1nt" //edi指向0值字节
"movl %4,%3n" //欲复制数->ecx
"1:tdecl %3nt"//ecx--
"js 2fnt" //若ecx<0,跳到标号2
"lodsb nt" //否则取ds:[esi]处的字节->al,esi++
"stosb nt" //存储到es:[edi]处,edi++
"testb %%al,%%alnt"//该字节是否为0
"jne 1bn" //不是则跳到1,接续复制
"2:txorl %2,%2nt" //将al清0
"stosb" //存储到es:[edi]处
:
:"S"(src),"D"(dest),"a"(0),"c"(0xffffffff),"g"(count)
:"si","di","ax","cx"
);
return dest;
}
/*
*将以一个字符串和另一个字符串比较
*参数:cs-源字符串指针,ct-目的字符串指针
*%0-eax(_res),%1-edi(cs),%2-esi(ct)
*返回:串1>串2 返回1;串1=串2,返回0,串1<串2,返回-1
*/
extern inline int strcmp(const char* cs,cosnt chat* ct)
{
register int __asm__("ax"); //寄存器变量
__asm__("cldn" //清方向位
"1:tlodsbnt" //取字符串2的字节ds:[esi]->al,esi++
"scasb nt" //al与字符串1的字节es:[edi]比较,edi++
"jne 2fnt" //如果不相等,跳转到2
"testb %%al,%alnt" //该字节是否为0(字符串结尾)
"jne 1bnt" //不是0,跳转到标号1,继续比较
"xorl %%eax,%%eaxnt" //是0,返回值eax
"jmp 3fn" //跳转到标号3结束
"2:tmovl %1,%%eaxnt"//eax置1
"jl 3fnt" //若前面比较总串2<串1,返回正值,结束
"negl %%eaxn" //否则eax=-eax,返回负值,结束
"3:"
:"=a"(_res)
:"D"(cs),"S"(ct)
:"si","di"
);
return _res;
}
/*
*字符串1与字符串2的前count字符比较
*参数:cs-字符串1,st-字符串2,count比较的字节数
*%0-eax(_res),%1-edi(cs),%2-esi(ct),%3-ecx(count)
*返回:串1 > 串2,则返回1,串1 = 串2,则返回0,串1< 串2,则返回-1
*/
extern inlint int strncmp(const char*cs,cosnt char*st,int count)
{
register _res __asm__("ax"); //寄存器变量
__asm__("cldn" //清方向位
"1:tdecl %3nt" //count--
"js 2fnt" //如果count<0,跳转到2
"lodsbnt" //取串2的字符ds:[esi]->al,esi++
"scasbnt" //比较al与串1的字符es:[edi],edi++
"jne 3fnt" //如果不等,跳转到标号3
"testb %%al,%%alnt" //该字符是否是NULL
"jne 1bn" //不是NULL,则跳转到1,继续比较
"2:txorl %%eax,%%eaxnt" //是NULL,则eax清零
"jmp 4fn" //前前跳转到4,结束
"3:tmovl $1,%%eaxnt" //置eax为1
"jl 4fnt" //如果串2<串1,返回1
"negl %%eaxn" //否则返回-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");//寄存器变量
__asm__("cldnt" //清方向位
"movb %%al,%%ahn" //将欲比较的字符转移到ah
"1:tlodsb nt" //取ds:[esi]->al,esi++
"cmpb %%ah,%%alnt" //字符串中字符al与指定字符ah比较
"je 2fnt" //相等,跳转到2处
"testb %%al,%%alnt" //al中字符是NULL字符吗(字符串末尾)
"jne 1bnt" //不是,则跳转到1,继续比较
"movl $1,%1n" //是,则说明没有找到
"2:t movl %1,%0nt" //将指向匹配字符后一个字节的指针->eax
"decl %0" //eax--
:"=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__("cldnt" //
"movb %%al,%%ahn" //将要寻找字符放到ah中
"1:tlodsb nt" //取字符串中字符ds:[esi]->al,esi++
"cmpb %%ah,%%alnt" //字符串中字符al与指定字符ah比较
"jne 2fnt" // 不相等,跳转到2处
"movl %%esi,%0nt" // 将字符指针保存到edx中
"decl %0n" // 指针减1,指向匹配字符处
"2:ttestb %%al,%%alnt" // 比较的字符是0吗(字符串末尾)
"jne 1b" // 不是就跳转到1处,继续比较
:"d="(_res)
:""(0),"S"(s),"a"(c)
:"ax","di"
);
return _res;
}
/*
*在字符串1中寻找第一个字符序列,该字符序列中任何字符都包含在字符串2中
*参数:cs-字符串1指针,ct字符串2指针
*%0-esi(res),%1-eax(0),%2-ecx(0xffffffff),%3-ecx(cs),%4-(ct)
*/
extern inline int strspn(cosnt char*cs,const char*ct)
{
register char* __res __asm__("si");//res是寄存器变量esi
__asm__("cldnt" //
"movl %4,%%edint" //首先计算串2长度.串2指针放入edi中
"repnent" //比较al(0)与串2中的字符(es:[edi]),edi++
"scasbnt" //如果不等就继续比较,ecx递减
"notl %%ecxnt" //ecx中没位取饭反
"decl %%ecxnt" //ecx--,得到串2长度
"movl %%ecx.%edxn" //将串2长度值放入edx中
"1:tlodsbnt" //取串1字符ds:[esi]->al,esi++
"testb %%al,%%alnt" //该字符等于0值吗(串1结尾)
"je 2fnt" //如果是,跳转到2处
"movl %4,%%edint" //取串2指针放入edi中
"movl %%edi,%%ecxnt" //在将串2长度放入ecx中
"repne nt" // 在比较al与串2中字符es:[edi],edi++
"scasb nt" //不等就继续比较
"je 1bn" // 相等就跳转到1处
"2:tdecl %0" //edi--指向最后一个包含在串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(0xffffffff),%3-ecx(cs),%4-(ct)
*返回:返回字符串1中不包含字符串2中任何字符的首个字符序列的长度值
*/
extern inline int strcspn(cosnt char*s,cosnt char*ct)
{
register char* __res __asm__("si"); //res寄存器变量esi
__asm__("cldnt" //
"movl %4,%%edint" //首先计算串2的长度,串2指针放入edi中
"repnent" //比较al(0)与串2中的字符(es:[edi])
"scasbnt" //不等就继续比较
"notl %%ecxnt" //ecx中每位取反
"decl %%ecxnt" //ecx--,得到串2长度值
"movl %%ecx,%%edxn" //将串2的长度值暂放入edx中
"1:tlodsbnt" //取串1字符ds:[esi]->al,esi++
"testb %%al,%%alnt" //该字符等于0(串1结尾)
"je 2fnt" //如果是,则跳转到2处
"movl %4,%%edint" //取串2头指针放入ecx中
"movl %%edx,%%ecxnt" //再将串2的长度值放入ecx中
"repne nt" //比较al与串2中字符es:[edi]
"scasb nt" //如果不等就继续比较
"jne 1bn" //如果不等就跳转到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指针,st-字符串2指针
*%0-esi(res),%1-eax(0),%2-ecx(0xffffffff),%3-ecx(cs),%4-(ct)
*返回字符串1中首个包含字符串2中字符的指针
*/
extern inline char* strbrk(const char*cs,const char*ct)
{
register char*__res __asm__("si");//res是寄存器变量(esi)
__asm__("cldnt" //
"movl %4,%%edint" //首先计算串2的长度,串2指针放入edi中
"repne nt" //比较al(0)与串2中的字符(es:[edi])
"scasb nt" //如果不等就继续比较
"notl %%ecxnt" //ecx中每位取反
"decl %%ecxnt" //ecx--,得到串2长度值
"movl %%ecx,%%edxn" //将串2的长度值暂放在edx中
"1:tlodsbnt" //取串1字符ds:[esi]->al,
"testb %%al,%%alnt" //该字符等于0值吗(串1结尾)
"je 2fnt" //如果是,则向前跳转到2处
"movl %4,%%edint" //取串2头指针放入edi中
"movl %%edx,%%ecxnt" //再将串2的长度值放入ecx中
"repnent" //比较al与串2字符es:[edi]
"scasbnt" //不等就继续比较
"jne 1bnt" //不相等,就跳转套标号1处
"decl %0nt" //esi--,指向一个包含在串2的字符
"jmp 3fn" //向前跳转到3处
"2:txorl %0,%0n" //没有找到符合条件的,将返回值为NULL
"3:" //
:"=S"(__res)
:"a"(0),"c"(0xffffffff),""(cs),"g"(ct)
:"ax","cx","dx","di"
);
return __res;
}
/*
*在字符串1中寻到首个匹配整个字符串2的字符串
*参数:cs-,ct-
*%0-eax(res),%1-eax(0),%2-ecx(0xffffffff),%3-esi(cs),%4-(ct)
*返回:返回字符串1中首个匹配字符串2的字符串的指针
*/
extern inline char* strstr(const char*cs cosnt char*ct)
{
register char* __res __asm__("ax");//res是寄存器变量
__asm__("cldnt" //
"movl %4,%%edint" //首先计算串2的长度,串2指针放入edi中
"repnent" //比较al(0)与串2的字符es:[edi]
"scasbnt" //不等就继续比较
"notl %%ecxnt" //ecx每位取反
"decl %%ecxnt" //ecx--,得到串2长度
"movl %%ecx,%%edxn" //串2长度暂放edx中
"1:tmovl %4,%%edint" //串2头指针放入edi中
"movl %%esi,%%eaxnt" //取串1指针放入eax中
"movl %%edx,%%ecxnt" //将串2长度放入ecx中
"repent" //比较串1和串2字符ds[esi],es[edi]
"cmpsbnt" //若对应字符相等就一直比较下去
"je 2fnt" //全等就跳转到2
"xchgl %%eax,%%esint" //串1头指针-esi,比较结果的串1指针-eax
"incl %%esint" //串1头指针指向下一个字符
"cmpb $0,-1(%%eax)nt" //串1指针eax-1所指字节是0吗
"jne 1bnt" //不是则跳转到标号1,继续从串1的第二个字符比较
"xorl %%eax,%%eaxnt" //清eax,表示没有匹配
"2:" //
:"=a"(_res)
:""(0),"c"(0xffffffff),"S"(cs),"g"(ct)
:"cx","dx","di","si"
);
return __res;
}
/*
*计算字符串长度
*参数:s-字符串
*%0-ecx(res),%1-edi(s),%2-eax(0),%3-ecx(0xffffffff)
*返回:返回字符串长度
*/
extern inline int strlen(const char*s)
{
register int __res __asm__("cx");//_res是寄存器变量
__asm__("cldnt" //
"repnent" //al(0)与字符串中字符es:[edi]比较
"scasbnt" //若不等就一直比较
"notl %0nt" //ecx取反
"decl %0" //ecx--,得到字符串的长度值
:"=c"(_res) //
:"D"(s),"a"(0),""(0xffffffff)
:"di"
);
return _res;
}
//用于临时存放指向被分析字符串的指针
extern char *__strtok;
/*
*利用字符串2中的字符串将字符串1分别分割成标记序列
*将串1看作是包含零个或多个单词的序列,并有分割符字符串2中的一个或多个字符分开
*第一次调用strtok时,将返回指向字符串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中第一个token,如果没有找到token,则返回一个null指针
*后续使用字符串s指针为null的调用,将在原字符串s中搜索下一个token
*/
extern inline char* strtok(char*s,const char*ct)
{
register char* __res __asm__("si");//_res是寄存器值
__asm__("testl %1,%1nt" //首先esi(字符串1指针s)是否为null
"jne 1f" //如果不是,则表明是首次调用本函数,跳到1
"test1 %0,%0nt" //如果是NULL,则表示此次是后续处理,测ebx(_strtok)
"je 8fnt" //如果ebx指针式NULL,则不能处理,跳转结束
"movl %0,%1n" //
"1:txorl %0,%0nt" //清ebx指针
"movl $-1,%%ecxnt" //值ecx为0xffffffff
"xorl %%eax,%%eaxnt" //清除eax
"cldnt" //清方向位
"movl %4,%%edint" //接下来求字符串2的长度.edi指向字符串2
"repnent" //将al(0)与es:[edi]比较,且edi++
"scasb nt" //知道找到字符串2的结束null字符,或计数ecx=0
"notl %%ecxnt" //ecx取反
"decl %%ecsnt" //ecx--,得到字符串2的长度
"je 7fnt" //(分隔符字符串空)字符串2长度为0,,跳到7
//
"movl %%ecx,%%edxn" //
"2:tlodsbnt" //
"testb %%al,%%alnt" //
"je 7fnt" //
"movl %4,%%edint" //
"movl %%edx,%%ecxnt" //
"repne nt" //
"scasb nt" //
"je 2bnt" //
"decl %1nt" //
"cmpb $0,(%1)nt" //
"je 7fnt" //
"movl %1,%0n" //
"3:tlodsbnt" //
"testb %%al,%%alnt" //
"je 5fnt" //
"movl %4,%%edint" //
"movl %%edx,%%ecxnt" //
"repne nt" //
"scasb nt" //
"jne 3bnt" //
"decl %1nt" //
"cmpb $0,(%1)nt" //
"je 5fnt" //
"movb $0,(%1)nt" //
"incl %1nt" //
"jmp 6fn" //
"5:txorl %1,%1n" //
"6:tcmpb $0,($0)nt" //
"jne 7fnt" //
"xorl %0,%0n" //
"7:ttestl %0,%0nt" //ebx指针位null吗?
"jne 8fnt" //若不是跳到8,结束汇编
"movl %0,%1n" //将esi置位NULL
"8:" //
:"=b"(__res),"=S"(__strtok)//
:""(_strtok),"l"(s),"g"(ct)//
:"ax","cx","dx","di" //
);
return _res;
}
/*
*内存块复制.从源地址src处开始复制n个字节到目的地址dest处
*参数:dest-目的地址,src-源地址,n-字节数
*%0-ecx(n),%1(esi src),%2(edi dest)
*/
extern inline void * memory()
{
__asm__("cldnt" //清方向位
"repnt" //重复执行复制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,cost void*src,int n)
{
if(dest>src) //
__asm__("cldnt" //清方向位
"repnt" //从ds:[esi]到es:[edi],且esi+,edi++
"movsb" //重复执行ecx确定的字节数
: //
:"c"(n),"S"(src),"D"(dest) //
:"cx","si","di" //
); //
else //
__asm__("stdnt" //置方向位,从末端开始复制
"repnt" //从ds:[esi]到es:[edi],且esi++,edi++
"movsb" //复制ecx个字节
: //
:"c"(n),"S"(src+n-1),"D"(dest)//
:"cx","si","di" //
); //
return dest; //
}
/*
*比较n个字节的两块内存(两个字符串),即使遇上NULL字节也不停止比较
*参数:cs-内存块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 int memcmp(cosnt void *cs,cosnt void*ct,int count)
{
register int _res __asm__("ax"); //_res是寄存器变量
__asm__("cldnt" //清方向位
"repent" //如果相等则重复
"cmpsbnt" //比较ds:[esi],es:[edi]内存,并且esi++,edi++
"je 1fnt" //如果都相同,则跳转到标号1,返回0值
"movl $1,%%eaxnt" //否则eax置1
"jl 1fnt" //若块2内容值小于块1,跳到1
"negl %%eaxn" //否则eax=-eax
"1:" //
:"=a"(_res)
:""(0),"D"(cs),"S"(ct),"c"(count)
:"si","di","cx"
);
return _res;
}
/*
*在n字节大小的内存块(字符串)中寻找指定的字符
*参数:cs-指定内存的地址,c-指定的字符,count-内存块长度
*%0-edi(_res), %1-eax(字符c), %2-edi(内存块地址cs), %3-ecx(字节数count)
*/
extern inline void * memchr(const void*cs,cahr c,int count)
{
register void * __res __asm__("di"); //_res是寄存器变量
if(!count) //如果内存长度=0,返回NULL
return NULL; //
__asm__("cld nt" //清方向位
"repnent" //如果不相等则重复执行下面语句
"scasbnt" //al中字符与es:[edi]字符作比较,且edi++
"je 1fnt" //如果相等则跳转到标号1处
"movl $1,%0n" //否则edi中置1
"1:tdecl %0" //让edi指向找到的字符
:"=D"(_res) //
:"a"(c),"D"(cs),"c"(count) //
:"cx" //
//
); //
return __res; //
}
/*
*用字符填写指定长度内存块
*用字符c填写s指向的内存区域,共填写count字节
*%1-eax(字符c),%2-edi(内存地址),%3-ecx(字节数count)
*/
extern inline void* memset(void *s,char c,int count)
{
__asm__("cldnt" //清方向位
"repnt" //重复ecx指定的次数
"stosb" //将al中字节放入es:[edi]中,并且edi++
: //
:"a"(c),"D"(s),"c"(count) //
:"cx","di" //
); //
return s; //
}
#endif
最后
以上就是健康羽毛为你收集整理的linux-011之string.h头文件的全部内容,希望文章能够帮你解决linux-011之string.h头文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复