?? string.h
字號:
#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=數據空間,這應該是常規(guī)的。絕大多數字符串函數都是經手工進行大量* 優(yōu)化的,尤其是函數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 字節(jié)??al,并更新esi。 "stosb\n\t" // 存儲字節(jié)al??ES:[edi],并更新edi。 "testb %%al,%%al\n\t" // 剛存儲的字節(jié)是0? "jne 1b" // 不是則向后跳轉到標號1 處,否則結束。::"S" (src), "D" (dest):"si", "di", "ax"); return dest; // 返回目的字符串指針。}//// 拷貝源字符串count 個字節(jié)到目的字符串。// 如果源串長度小于count 個字節(jié),就附加空字符(NULL)到目的字符串。// 參數:dest - 目的字符串指針,src - 源字符串指針,count - 拷貝字節(jié)數。// %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 字節(jié)??al,并且esi++。 "stosb\n\t" // 存儲該字節(jié)??es:[edi],并且edi++。 "testb %%al,%%al\n\t" // 該字節(jié)是0? "jne 1b\n\t" // 不是,則向前跳轉到標號1 處繼續(xù)拷貝。 "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]字節(jié),并更新edi++, "scasb\n\t" // 直到找到目的串中是0 的字節(jié),此時edi 已經指向后1 字節(jié)。 "decl %1\n" // 讓es:[edi]指向0 值字節(jié)。 "1:\tlodsb\n\t" // 取源字符串字節(jié)ds:[esi]??al,并esi++。 "stosb\n\t" // 將該字節(jié)存到es:[edi],并edi++。 "testb %%al,%%al\n\t" // 該字節(jié)是0? "jne 1b" // 不是,則向后跳轉到標號1 處繼續(xù)拷貝,否則結束。::"S" (src), "D" (dest), "a" (0), "c" (0xffffffff):"si", "di", "ax", "cx"); return dest; // 返回目的字符串指針。}//// 將源字符串的count 個字節(jié)復制到目的字符串的末尾處,最后添一空字符。// 參數:dest - 目的字符串,src - 源字符串,count - 欲復制的字節(jié)數。// %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]字節(jié),edi++。 "scasb\n\t" // 直到找到目的串的末端0 值字節(jié)。 "decl %1\n\t" // edi 指向該0 值字節(jié)。 "movl %4,%3\n" // 欲復制字節(jié)數??ecx。 "1:\tdecl %3\n\t" // ecx--(從0 開始計數)。 "js 2f\n\t" // ecx <0 ?,是則向前跳轉到標號2 處。 "lodsb\n\t" // 否則取ds:[esi]處的字節(jié)??al,esi++。 "stosb\n\t" // 存儲到es:[edi]處,edi++。 "testb %%al,%%al\n\t" // 該字節(jié)值為0? "jne 1b\n" // 不是則向后跳轉到標號1 處,繼續(xù)復制。 "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 的字節(jié)ds:[esi]??al,并且esi++。 "scasb\n\t" // al 與字符串1 的字節(jié)es:[edi]作比較,并且edi++。 "jne 2f\n\t" // 如果不相等,則向前跳轉到標號2。 "testb %%al,%%al\n\t" // 該字節(jié)是0 值字節(jié)嗎(字符串結尾)? "jne 1b\n\t" // 不是,則向后跳轉到標號1,繼續(xù)比較。 "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,繼續(xù)比較。 "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)。// 返回:返回字符串中第一次出現(xiàn)匹配字符的指針。若沒有找到匹配的字符,則返回空指針。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,繼續(xù)比較。 "movl $1,%1\n" // 是,則說明沒有找到匹配字符,esi 置1。 "2:\tmovl %1,%0\n\t" // 將指向匹配字符后一個字節(jié)處的指針值放入eax "decl %0" // 將指針調整為指向匹配的字符。: "=a" (__res): "S" (s), "" (c):"si"); return __res; // 返回指針。}//// 尋找字符串中指定字符最后一次出現(xiàn)的地方。(反向搜索字符串)// 參數:s - 字符串,c - 欲尋找的字符。// %0 - edx(__res),%1 - edx(0),%2 - esi(字符串指針s),%3 - eax(字符c)。// 返回:返回字符串中最后一次出現(xiàn)匹配字符的指針。若沒有找到匹配的字符,則返回空指針。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 處,繼續(xù)比較。: "=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" // 如果不相等就繼續(xù)比較(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" // 如果不相等就繼續(xù)比較。 "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" // 如果不相等就繼續(xù)比較(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 + -