📄 string.h
字号:
#ifndef _STRING_H_#define _STRING_H_/*
其实vc编译器本身包含了这些函数定义,我们完全可以把string.h内的函数定义
都注释掉,然后为每个.c文件编译时加上/Ox编译选项即可。
*/
#ifndef NULL#define NULL 0#endif#ifndef _SIZE_T#define _SIZE_Ttypedef unsigned int size_t;#endifextern char *strerror (int errno);/** 这个字符串头文件以内嵌函数的形式定义了所有字符串操作函数。使用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{
pushf
mov esi,src
mov edi,dest
cld // 清方向位。
l1: lodsb // 加载DS:[esi]处1 字节->al,并更新esi。
stosb // 存储字节al->ES:[edi],并更新edi。
test al,al // 刚存储的字节是0?
jne l1 // 不是则跳转到标号l1 处,否则结束。
popf
}
return 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)。static _inline char *strncpy (char *dest, const char *src, int count){ _asm{
pushf
mov esi,src
mov edi,dest
mov ecx,count
cld // 清方向位。
l1: dec ecx // 寄存器ecx--(count--)。
js l2 // 如果count<0 则向前跳转到标号l2,结束。
lodsb // 取ds:[esi]处1 字节->al,并且esi++。
stosb // 存储该字节->es:[edi],并且edi++。
test al,al // 该字节是0?
jne l1 // 不是,则向前跳转到标号l1 处继续拷贝。
rep stosb // 否则,在目的串中存放剩余个数的空字符。
l2: popf
} return dest; // 返回目的字符串指针。}/*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 {
pushf
mov esi,src
mov edi,dest
xor al,al
mov ecx,0xffffffff
cld // 清方向位。
repne scasb // 比较al 与es:[edi]字节,并更新edi++,
// 直到找到目的串中是0 的字节,此时edi 已经指向后1 字节。
dec edi // 让es:[edi]指向0 值字节。
l1: lodsb // 取源字符串字节ds:[esi]->al,并esi++。
stosb // 将该字节存到es:[edi],并edi++。
test al,al // 该字节是0?
jne l1 // 不是,则向后跳转到标号1 处继续拷贝,否则结束。
popf
} return dest; // 返回目的字符串指针。}/*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)。static _inline char *strncat (char *dest, const char *src, int count){ _asm {
pushf
mov esi,src
mov edi,dest
xor al,al
mov ecx,0xffffffff
cld // 清方向位。
repne scasb // 比较al 与es:[edi]字节,edi++。直到找到目的串的末端0 值字节。
dec edi // edi 指向该0 值字节。
mov ecx,count // 欲复制字节数??ecx。
l1: dec ecx // ecx--(从0 开始计数)。
js l2 // ecx <0 ?,是则向前跳转到标号l2 处。
lodsb // 否则取ds:[esi]处的字节->al,esi++。
stosb // 存储到es:[edi]处,edi++。
test al,al // 该字节值为0?
jne l1 // 不是则向后跳转到标号1 处,继续复制。
l2: xor al,al // 将al 清零。
stosb // 存到es:[edi]处。
popf
} return dest; // 返回目的字符串指针。}/*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; // 返回目的字符串指针。
}*/
//// 将一个字符串与另一个字符串进行比较。// 参数:csrc - 字符串1,ct - 字符串2。// %0 - eax(__res)返回值,%1 - edi(csrc)字符串1 指针,%2 - esi(ct)字符串2 指针。// 返回:如果串1 > 串2,则返回1;串1 = 串2,则返回0;串1 < 串2,则返回-1。extern _inline intstrcmp (const char *csrc, const char *ct){// register int __res; // __res 是寄存器变量(eax)。 _asm{
pushf
mov edi,csrc
mov esi,ct
cld // 清方向位。
l1: lodsb // 取字符串2 的字节ds:[esi]??al,并且esi++。
scasb // al 与字符串1 的字节es:[edi]作比较,并且edi++。
jne l2 // 如果不相等,则向前跳转到标号2。
test al,al // 该字节是0 值字节吗(字符串结尾)?
jne l1 // 不是,则向后跳转到标号1,继续比较。
xor eax,eax // 是,则返回值eax 清零,
jmp l3 // 向前跳转到标号3,结束。
l2: mov eax,1 // eax 中置1。
jl l3 // 若前面比较中串2 字符<串1 字符,则返回正值,结束。
neg eax // 否则eax = -eax,返回负值,结束。
// l3: mov __res,eax
l3: popf
}// return __res; // 返回比较结果。}/*extern _inline int
strcmp (const char *csrc, 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" (csrc), "S" (ct):"si", "di");
return __res; // 返回比较结果。
}*/
//// 字符串1 与字符串2 的前count 个字符进行比较。// 参数:csrc - 字符串1,ct - 字符串2,count - 比较的字符数。// %0 - eax(__res)返回值,%1 - edi(csrc)串1 指针,%2 - esi(ct)串2 指针,%3 - ecx(count)。// 返回:如果串1 > 串2,则返回1;串1 = 串2,则返回0;串1 < 串2,则返回-1。static _inline intstrncmp (const char *csrc, const char *ct, int count){// register int __res; // __res 是寄存器变量(eax)。
_asm{
pushf
mov edi,csrc
mov esi,ct
mov ecx,count
cld // 清方向位。
l1: dec ecx // count--。
js l2 // 如果count<0,则向前跳转到标号2。
lodsb // 取串2 的字符ds:[esi]??al,并且esi++。
scasb // 比较al 与串1 的字符es:[edi],并且edi++。
jne l3 // 如果不相等,则向前跳转到标号3。
test al,al // 该字符是NULL 字符吗?
jne l1 // 不是,则向后跳转到标号1,继续比较。
l2: xor eax,eax // 是NULL 字符,则eax 清零(返回值)。
jmp l4 // 向前跳转到标号4,结束。
l3: mov eax,1 // eax 中置1。
jl l4 // 如果前面比较中串2 字符<串2 字符,则返回1,结束。
neg eax // 否则eax = -eax,返回负值,结束。
// l4: mov __res,eax
l4: popf
}// return __res; // 返回比较结果。}/*extern _inline int
strncmp (const char *csrc, 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" (csrc), "S" (ct), "c" (count):"si", "di",
"cx");
return __res; // 返回比较结果。
}*/
//// 在字符串中寻找第一个匹配的字符。// 参数:s - 字符串,c - 欲寻找的字符。// %0 - eax(__res),%1 - esi(字符串指针s),%2 - eax(字符c)。// 返回:返回字符串中第一次出现匹配字符的指针。若没有找到匹配的字符,则返回空指针。static _inline char *strchr (const char *s, char c){// register char *__res; // __res 是寄存器变量(eax)。
_asm{
pushf
mov esi,s
mov ah,c
cld // 清方向位。
l1: lodsb // 取字符串中字符ds:[esi]->al,并且esi++。
cmp al,ah // 字符串中字符al 与指定字符ah 相比较。
je l2 // 若相等,则向前跳转到标号2 处。
test al,al // al 中字符是NULL 字符吗?(字符串结尾?)
jne l1 // 若不是,则向后跳转到标号1,继续比较。
mov esi,1 // 是,则说明没有找到匹配字符,esi 置1。
l2: mov eax,esi // 将指向匹配字符后一个字节处的指针值放入eax
dec eax // 将指针调整为指向匹配的字符。
// mov __res,eax
popf
}// return __res; // 返回指针。}/*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。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -