?? string.h
字號:
"movl %%edx,%%ecx\n\t" // 再將串2 的長度值放入ecx 中。 "repne\n\t" // 比較al 與串2 中字符es:[edi],并且edi++。 "scasb\n\t" // 如果不相等就繼續(xù)比較。 "jne 1b\n" // 如果不相等,則向后跳轉(zhuǎ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 中的任何字符。// 參數(shù):cs - 字符串1 的指針,ct - 字符串2 的指針。// %0 -esi(__res),%1 -eax(0),%2 -ecx(0xffffffff),%3 -esi(串1 指針cs),%4 -(串2 指針ct)。// 返回字符串1 中首個包含字符串2 中字符的指針。extern inline char *strpbrk (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 結(jié)尾)? "je 2f\n\t" // 如果是,則向前跳轉(zhuǎn)到標號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ù)比較。 "jne 1b\n\t" // 如果不相等,則向后跳轉(zhuǎn)到標號1 處。 "decl %0\n\t" // esi--,指向一個包含在串2 中的字符。 "jmp 3f\n" // 向前跳轉(zhuǎn)到標號3 處。 "2:\txorl %0,%0\n" // 沒有找到符合條件的,將返回值為NULL。"3:": "=S" (__res): "a" (0), "c" (0xffffffff), "" (cs), "g" (ct):"ax", "cx", "dx", "di"); return __res; // 返回指針值。}//// 在字符串1 中尋找首個匹配整個字符串2 的字符串。// 參數(shù):cs - 字符串1 的指針,ct - 字符串2 的指針。// %0 -eax(__res),%1 -eax(0),%2 -ecx(0xffffffff),%3 -esi(串1 指針cs),%4 -(串2 指針ct)。// 返回:返回字符串1 中首個匹配字符串2 的字符串指針。extern inline char *strstr (const char *cs, const char *ct){ register char *__res __asm__ ("ax"); // __res 是寄存器變量(eax)。 __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" /* NOTE! This also sets Z if searchstring='' *//* 注意!如果搜索串為空,將設(shè)置Z 標志 */// 得串2 的長度值。 "movl %%ecx,%%edx\n" // 將串2 的長度值暫放入edx 中。 "1:\tmovl %4,%%edi\n\t" // 取串2 頭指針放入edi 中。 "movl %%esi,%%eax\n\t" // 將串1 的指針復(fù)制到eax 中。 "movl %%edx,%%ecx\n\t" // 再將串2 的長度值放入ecx 中。 "repe\n\t" // 比較串1 和串2 字符(ds:[esi],es:[edi]),esi++,edi++。 "cmpsb\n\t" // 若對應(yīng)字符相等就一直比較下去。 "je 2f\n\t" /* also works for empty string, see above *//* 對空串同樣有效,見上面 */// 若全相等,則轉(zhuǎn)到標號2。 "xchgl %%eax,%%esi\n\t" // 串1 頭指針??esi,比較結(jié)果的串1 指針??eax。 "incl %%esi\n\t" // 串1 頭指針指向下一個字符。 "cmpb $0,-1(%%eax)\n\t" // 串1 指針(eax-1)所指字節(jié)是0 嗎? "jne 1b\n\t" // 不是則跳轉(zhuǎn)到標號1,繼續(xù)從串1 的第2 個字符開始比較。 "xorl %%eax,%%eax\n\t" // 清eax,表示沒有找到匹配。"2:": "=a" (__res): "" (0), "c" (0xffffffff), "S" (cs), "g" (ct):"cx", "dx", "di", "si"); return __res; // 返回比較結(jié)果。}//// 計算字符串長度。// 參數(shù):s - 字符串。// %0 - ecx(__res),%1 - edi(字符串指針s),%2 - eax(0),%3 - ecx(0xffffffff)。// 返回:返回字符串的長度。extern inline intstrlen (const char *s){ register int __res __asm__ ("cx"); // __res 是寄存器變量(ecx)。 __asm__ ("cld\n\t" // 清方向位。 "repne\n\t" // al(0)與字符串中字符es:[edi]比較, "scasb\n\t" // 若不相等就一直比較。 "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 中的一個或多個字符分開。// 第一次調(diào)用strtok()時,將返回指向字符串1 中第1 個token 首字符的指針,并在返回token 時將// 一null 字符寫到分割符處。后續(xù)使用null 作為字符串1 的調(diào)用,將用這種方法繼續(xù)掃描字符串1,// 直到?jīng)]有token 為止。在不同的調(diào)用過程中,分割符串2 可以不同。// 參數(shù):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 指針。// 后續(xù)使用字符串s 指針為null 的調(diào)用,將在原字符串s 中搜索下一個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" // 如果不是,則表明是首次調(diào)用本函數(shù),跳轉(zhuǎn)標號1。 "testl %0,%0\n\t" // 如果是NULL,則表示此次是后續(xù)調(diào)用,測ebx(__strtok)。 "je 8f\n\t" // 如果ebx 指針是NULL,則不能處理,跳轉(zhuǎn)結(jié)束。 "movl %0,%1\n" // 將ebx 指針復(fù)制到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 的結(jié)束null 字符,或計數(shù)ecx==0。 "notl %%ecx\n\t" // 將ecx 取反, "decl %%ecx\n\t" // ecx--,得到字符串2 的長度值。 "je 7f\n\t" /* empty delimeter-string *//* 分割符字符串空 */// 若串2 長度為0,則轉(zhuǎn)標號7。 "movl %%ecx,%%edx\n" // 將串2 長度暫存入edx。 "2:\tlodsb\n\t" // 取串1 的字符ds:[esi]??al,并且esi++。 "testb %%al,%%al\n\t" // 該字符為0 值嗎(串1 結(jié)束)? "je 7f\n\t" // 如果是,則跳轉(zhuǎn)標號7。 "movl %4,%%edi\n\t" // edi 再次指向串2 首。 "movl %%edx,%%ecx\n\t" // 取串2 的長度值置入計數(shù)器ecx。 "repne\n\t" // 將al 中串1 的字符與串2 中所有字符比較, "scasb\n\t" // 判斷該字符是否為分割符。 "je 2b\n\t" // 若能在串2 中找到相同字符(分割符),則跳轉(zhuǎn)標號2。 "decl %1\n\t" // 若不是分割符,則串1 指針esi 指向此時的該字符。 "cmpb $0,(%1)\n\t" // 該字符是NULL 字符嗎? "je 7f\n\t" // 若是,則跳轉(zhuǎn)標號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 結(jié)束,跳轉(zhuǎn)到標號5。 "movl %4,%%edi\n\t" // edi 再次指向串2 首。 "movl %%edx,%%ecx\n\t" // 串2 長度值置入計數(shù)器ecx。 "repne\n\t" // 將al 中串1 的字符與串2 中每個字符比較, "scasb\n\t" // 測試al 字符是否是分割符。 "jne 3b\n\t" // 若不是分割符則跳轉(zhuǎn)標號3,檢測串1 中下一個字符。 "decl %1\n\t" // 若是分割符,則esi--,指向該分割符字符。 "cmpb $0,(%1)\n\t" // 該分割符是NULL 字符嗎? "je 5f\n\t" // 若是,則跳轉(zhuǎn)到標號5。 "movb $0,(%1)\n\t" // 若不是,則將該分割符用NULL 字符替換掉。 "incl %1\n\t" // esi 指向串1 中下一個字符,也即剩余串首。 "jmp 6f\n" // 跳轉(zhuǎn)標號6 處。 "5:\txorl %1,%1\n" // esi 清零。 "6:\tcmpb $0,(%0)\n\t" // ebx 指針指向NULL 字符嗎? "jne 7f\n\t" // 若不是,則跳轉(zhuǎn)標號7。 "xorl %0,%0\n" // 若是,則讓ebx=NULL。 "7:\ttestl %0,%0\n\t" // ebx 指針為NULL 嗎? "jne 8f\n\t" // 若不是則跳轉(zhuǎn)8,結(jié)束匯編代碼。 "movl %0,%1\n" // 將esi 置為NULL。"8:": "=b" (__res), "=S" (___strtok): "" (___strtok), "1" (s), "g" (ct):"ax", "cx", "dx", "di"); return __res; // 返回指向新token 的指針。}//// 內(nèi)存塊復(fù)制。從源地址src 處開始復(fù)制n 個字節(jié)到目的地址dest 處。// 參數(shù):dest - 復(fù)制的目的地址,src - 復(fù)制的源地址,n - 復(fù)制字節(jié)數(shù)。// %0 - ecx(n),%1 - esi(src),%2 - edi(dest)。extern inline void *memcpy (void *dest, const void *src, int n){ __asm__ ("cld\n\t" // 清方向位。 "rep\n\t" // 重復(fù)執(zhí)行復(fù)制ecx 個字節(jié), "movsb" // 從ds:[esi]到es:[edi],esi++,edi++。::"c" (n), "S" (src), "D" (dest):"cx", "si", "di"); return dest; // 返回目的地址。}//// 內(nèi)存塊移動。同內(nèi)存塊復(fù)制,但考慮移動的方向。// 參數(shù):dest - 復(fù)制的目的地址,src - 復(fù)制的源地址,n - 復(fù)制字節(jié)數(shù)。// 若dest<src 則:%0 - ecx(n),%1 - esi(src),%2 - edi(dest)。// 否則:%0 - ecx(n),%1 - esi(src+n-1),%2 - edi(dest+n-1)。// 這樣操作是為了防止在復(fù)制時錯誤地重疊覆蓋。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" // 重復(fù)執(zhí)行復(fù)制ecx 字節(jié)。 ::"c" (n), "S" (src), "D" (dest):"cx", "si", "di"); else __asm__ ("std\n\t" // 置方向位,從末端開始復(fù)制。 "rep\n\t" // 從ds:[esi]到es:[edi],并且esi--,edi--, "movsb" // 復(fù)制ecx 個字節(jié)。 ::"c" (n), "S" (src + n - 1), "D" (dest + n - 1):"cx", "si", "di"); return dest;}//// 比較n 個字節(jié)的兩塊內(nèi)存(兩個字符串),即使遇上NULL 字節(jié)也不停止比較。// 參數(shù):cs - 內(nèi)存塊1 地址,ct - 內(nèi)存塊2 地址,count - 比較的字節(jié)數(shù)。// %0 - eax(__res),%1 - eax(0),%2 - edi(內(nèi)存塊1),%3 - esi(內(nèi)存塊2),%4 - ecx(count)。// 返回:若塊1>塊2 返回1;塊1<塊2,返回-1;塊1==塊2,則返回0。extern inline intmemcmp (const void *cs, const void *ct, int count){ register int __res __asm__ ("ax"); // __res 是寄存器變量。 __asm__ ("cld\n\t" // 清方向位。 "repe\n\t" // 如果相等則重復(fù), "cmpsb\n\t" // 比較ds:[esi]與es:[edi]的內(nèi)容,并且esi++,edi++。 "je 1f\n\t" // 如果都相同,則跳轉(zhuǎn)到標號1,返回0(eax)值 "movl $1,%%eax\n\t" // 否則eax 置1, "jl 1f\n\t" // 若內(nèi)存塊2 內(nèi)容的值<內(nèi)存塊1,則跳轉(zhuǎn)標號1。 "negl %%eax\n" // 否則eax = -eax。"1:": "=a" (__res): "" (0), "D" (cs), "S" (ct), "c" (count):"si", "di", "cx"); return __res; // 返回比較結(jié)果。}//// 在n 字節(jié)大小的內(nèi)存塊(字符串)中尋找指定字符。// 參數(shù):cs - 指定內(nèi)存塊地址,c - 指定的字符,count - 內(nèi)存塊長度。// %0 - edi(__res),%1 - eax(字符c),%2 - edi(內(nèi)存塊地址cs),%3 - ecx(字節(jié)數(shù)count)。// 返回第一個匹配字符的指針,如果沒有找到,則返回NULL 字符。extern inline void *memchr (const void *cs, char c, int count){ register void *__res __asm__ ("di"); // __res 是寄存器變量。 if (!count) // 如果內(nèi)存塊長度==0,則返回NULL,沒有找到。 return NULL; __asm__ ("cld\n\t" // 清方向位。 "repne\n\t" // 如果不相等則重復(fù)執(zhí)行下面語句, "scasb\n\t" // al 中字符與es:[edi]字符作比較,并且edi++, "je 1f\n\t" // 如果相等則向前跳轉(zhuǎn)到標號1 處。 "movl $1,%0\n" // 否則edi 中置1。 "1:\tdecl %0" // 讓edi 指向找到的字符(或是NULL)。: "=D" (__res): "a" (c), "D" (cs), "c" (count):"cx"); return __res; // 返回字符指針。}//// 用字符填寫指定長度內(nèi)存塊。// 用字符c 填寫s 指向的內(nèi)存區(qū)域,共填count 字節(jié)。// %0 - eax(字符c),%1 - edi(內(nèi)存地址),%2 - ecx(字節(jié)數(shù)count)。extern inline void *memset (void *s, char c, int count){ __asm__ ("cld\n\t" // 清方向位。 "rep\n\t" // 重復(fù)ecx 指定的次數(shù),執(zhí)行 "stosb" // 將al 中字符存入es:[edi]中,并且edi++。::"a" (c), "D" (s), "c" (count):"cx", "di"); return s;}#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -