📄 string.h
字号:
"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 + -