static inline char * strcpy(char * dest,const char *src)
{
int d0, d1;
__asm__ __volatile__("cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
:"=&S"(d0),"=&D"(d1)
: "0" (src),"1" (dest)
:"ax");
return dest;
}
Line 3: cld(clear direction flag) EFLAGS์ DF ํ๋๊ทธ๋ฅผ ํด๋ฆฌ์ดํ๋ค. DF ํ๋๊ทธ๊ฐ 0์ด๋ผ๋ฉด, string ์คํผ๋ ์ด์
์์ ์ธ๋ฑ์ค ๋ ์ง์คํฐ(ESI and/or EDI)๊ฐ ์ฆ๊ฐํ๋ค.
Line 4: lods(load string) ds:esi์์ 1/2/4๋ฐ์ดํธ๋ฅผ AL, AX ๋๋ EAX ๋ ์ง์คํฐ์ ๋ก๋ํ๋ค. ์ฝ์ ๋งํผ esi ๋ ์ง์คํฐ ๊ฐ์ด DFํ๋๊ทธ์ ๋ฐ๋ผ ์ฆ๊ฐ ๋๋ ๊ฐ์ํ๋ค.
Line 5: stos(store string) AL, AX ๋๋ EAX ๋ ์ง์คํฐ์์ 1/2/4 ๋ฐ์ดํธ๋ฅผ es:edi/di์ storeํ๋ค. ์ ์ฅํ ๋งํผ edi ๋ ์ง์คํฐ ๊ฐ์ด DFํ๋๊ทธ์ ๋ฐ๋ผ ์ฆ๊ฐ ๋๋ ๊ฐ์ํ๋ค.
Line 6~7: ์ฝ์ ๊ฐ(ax)๊ฐ NULL์ด ์๋๋ฉด 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ๋ค.
Line 8: ์ดํ ์๋ต
input: esi(dummy0), edi(dummy1)
output: esi(src), edi(dest)
์๋ณธ ์ฝ๋์๋ input ๋ ์ง์คํฐ๊ฐ clobber์ ๋ค์ด๊ฐ ์์ง๋ง, ์ง๊ธ์ ๊ทธ์ ๊ฐ์ ๋ฌธ๋ฒ์ ํ์ฉํ์ง ์๋๋ค. ํด๋น ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ๋ผ.
static inline char * strncpy(char * dest,const char *src,int count)
{
int d0, d1, d2;
__asm__ __volatile__("cld\n"
"1:\tdecl %2\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"rep\n\t"
"stosb\n"
"2:"
:"=&S" (d0),"=&D" (d1),"=&c" (d2)
:"0" (src), "1" (dest), "2" (count)
:"ax");
return dest;
}
Line 4~5: count์ ๊ฐ์ 1 ๊ฐ์ ์ํจ๋ค. ์์๋ผ๋ฉด, 2๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 6~9: strcpy์ ๋ด์ฉ๊ณผ ๋์ผ
Line 10~12: ๋จ์ count๋งํผ stosb ๋ฐ๋ณตํ๋ค. ์ฆ count๋งํผ NULL์ edi์ ๋ณต์ฌํ๋ค.
static inline char * strcat(char * dest,const char * src)
{
int d0, d1, d2, d3;
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
:"=&S"(d0), "=&D"(d1), "=&a"(d2), ="=&c" (d3)
:"0" (src),"1" (dest),"2" (0),"3" (0xffffffff));
return dest;
}
Line 3: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 4~6:
repne: zero flag๊ฐ 0์ผ๋ ๋์,
scas(scan string) ax/al/eax๋ฅผ edi ๋ ์ง์คํฐ์ ๊ฐ๊ณผ ๋น๊ต(cmp)ํ์ฌ ํ๋๊ทธ๋ฅผ ์ค์ ํ๋ค.
์ฆ, src์ NULL ์์น ๋ฐ๋ก ์ ๊น์ง ์ด๋ํ๋ค๋ ๋ง์ด๋ค.
Line 7~10: strcpy์ ๋์ผ
static inline char * strncat(char * dest,const char * src,int count)
{
int d0, d1, d2, d3;
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
"movl %8,%7\n"
"1:\tdecl %7\n\t"
"js 2f\n\t"
"lodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
:"=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
:"0" (src),"1" (dest),"2" (0),"3" (0xffffffff),"g" (count)
);
return dest;
}
Line 4: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 5~7:
repne: zero flag๊ฐ 0์ผ๋ ๋์,
scas(scan string) ax/al/eax๋ฅผ edi ๋ ์ง์คํฐ์ ๊ฐ๊ณผ ๋น๊ต(cmp)ํ์ฌ ํ๋๊ทธ๋ฅผ ์ค์ ํ๋ค.
์ฆ, src์ NULL ์์น ๋ฐ๋ก ์ ๊น์ง ์ด๋ํ๋ค๋ ๋ง์ด๋ค.
Line 8: ecx๋ฅผ ์ธ์๋ก ๋ฐ์ count๋ก ์ธํ
ํ๋ค.
Line 9~14: ecx๋ฅผ ๊ฐ์์ํค๋ฉฐ 1๋ฐ์ดํธ๋ฅผ ๋ณต์ฌํ๋ค(esi -> edi)
static inline int strcmp(const char * cs,const char * ct)
{
int d0, d1;
register int __res __asm__("ax");
__asm__("cld\n"
"1:\tlodsb\n\t"
"scasb\n\t"
"jne 2f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"jmp 3f\n"
"2:\tmovl $1,%%eax\n\t"
"jl 3f\n\t"
"negl %%eax\n"
"3:"
:"=a" (__res, "=&D" (d0),"=&S" (d1)
:"1" (cs), "2" (ct));
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~7: ds:esi์์ 1๋ฐ์ดํธ๋ฅผ ax์ ๋ก๋ํ๊ณ es:edi์ ๊ฐ๊ณผ cmpํ๋ค.
Line 8: ๊ฐ์ง ์๋ค๋ฉด 2๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 9~12: ax๊ฐ NULL์ธ์ง ํ์ธํ๋ค. ์๋๋ผ๋ฉด 1๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค. ๋ง๋ค๋ฉด, eax๋ฅผ 0์ผ๋ก ์ธํ
ํ๊ณ ๋ฆฌํดํ๋ค.
Line 13~15: 1์ ๋ฆฌํดํ ์ง, 1์ ๋ฆฌํดํ ์ง ๊ฒฐ์ ํ๋ค.
static inline int strncmp(const char * cs,const char * ct,int count)
{
int d0, d1, d2;
register int __res __asm__("ax");
__asm__("cld\n"
"1:\tdecl %6\n\t"
"js 2f\n\t"
"lodsb\n\t"
"scasb\n\t"
"jne 3f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %%eax,%%eax\n\t"
"jmp 4f\n"
"3:\tmovl $1,%%eax\n\t"
"jl 4f\n\t"
"negl %%eax\n"
"4:"
:"=a" (__res), "=&D" (d0), "=&S" (d1), "=&c" (d2)
:"1" (cs),"2" (ct),"3" (count));
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~7: count๋ฅผ ๊ฐ์ํ๊ณ ์์๋ผ๋ฉด 2๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 8~9: ds:esi์์ 1๋ฐ์ดํธ๋ฅผ ax์ ๋ก๋ํ๊ณ es:edi์ ๊ฐ๊ณผ cmpํ๋ค.
Line 10: ๊ฐ์ง ์๋ค๋ฉด 3๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 11~14: ax๊ฐ NULL์ธ์ง ํ์ธํ๋ค. ์๋๋ผ๋ฉด 1๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค. ๋ง๋ค๋ฉด, eax๋ฅผ 0์ผ๋ก ์ธํ
ํ๊ณ ๋ฆฌํดํ๋ค.
Line 15~17: 1์ ๋ฆฌํดํ ์ง, 1์ ๋ฆฌํดํ ์ง ๊ฒฐ์ ํ๋ค.
static inline char * strchr(const char * s,char c)
{
int d0;
register char * __res __asm__("ax");
__asm__("cld\n\t"
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"je 2f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n\t"
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
:"=a" (__res), "=&S" (s)
:"1" (s),"0" (c));
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6: c๋ฅผ ah์ผ๋ก ์ด๋
Line 7~8: ds:esi๋ก๋ถํฐ 1๋ฐ์ดํธ๋ฅผ ์ฝ๊ณ , al์ ์ ์ฅํ๊ณ ah์ ๋น๊ตํ๋ค.
Line 9: ๋์ผํ๋ฉด 2๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 10~11: NULL์ ๋๋ฌํ ๋๊น์ง 1๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 12~14: ๋ชป์ฐพ์ผ๋ฉด 0์ ๋ฆฌํดํ๊ณ , ์ฐพ์๋ค๋ฉด ์ฐพ์ ์ฃผ์(esi)๋ฅผ ๋ฆฌํดํ๋ค.
static inline char * strrchr(const char * s,char c)
{
int d0, d1;
register char * __res __asm__("dx");
__asm__("cld\n\t"
"movb %%al,%%ah\n"
"1:\tlodsb\n\t"
"cmpb %%ah,%%al\n\t"
"jne 2f\n\t"
"movl %%esi,%0\n\t"
"decl %0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
:"=d" (__res), "=&S" (d0), "=&a" (d1)
:"0" (0),"1" (s),"2" (c));
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6: c๋ฅผ ah์ผ๋ก ์ด๋
Line 7~8: ds:esi๋ก๋ถํฐ 1๋ฐ์ดํธ๋ฅผ ์ฝ๊ณ , al์ ์ ์ฅํ๊ณ ah์ ๋น๊ตํ๋ค.
Line 9: ๋์ผํ์ง ์์ผ๋ฉด 2๋ฒ ๋ผ๋ฒจ๋ก ์ ํํ๋ค.
Line 10~11: ๋ฐ๊ฒฌํ ์ฃผ์๋ฅผ __res์ ์ ์ฅํ๋ค.
Line 12~14: NULL์ ๋๋ฌํ์ง ์์๋ค๋ฉด 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ๋ค.
static inline int strspn(const char * cs, const char * ct)
{
int d0, d1;
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %6,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"je 1b\n"
"2:\tdecl %0"
:"=S" (__res), "=&a" (d0), "=&c" (d1)
:"1" (0),"2" (0xffffffff),"0" (cs),"g" (ct)
:"dx","di");
return __res-cs;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~11: ct์ ๊ธธ์ด๋ฅผ ๊ตฌํ์ฌ edx์ ์ ์ฅ.
Line 12~14: esi์์ 1๋ฐ์ดํธ๋ฅผ ์ฝ๊ณ al์ ์ ์ฅ, NULL์ธ์ง ํ์ธ
Line 15~19: ct ์ค al๊ณผ ์ผ์นํ๋ ๋ฐ์ดํธ๊ฐ ์๋์ง ํ์ธ, ์๋ค๋ฉด ๋ฆฌํดํ๋ค.
Line 20: ์ผ์นํ๋ ๋ฌธ์๊ฐ ์๋ค๋ฉด(je) 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ ๋ค์ ๋ฌธ์๋ฅผ ๋น๊ตํ๋ค.
static inline int strcspn(const char * cs, const char * ct)
{
int d0, d1;
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %6,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n"
"2:\tdecl %0"
:"=S" (__res), "=&a" (d0), "=&c" (d1)
:"1" (0),"2" (0xffffffff),"0" (cs),"g" (ct)
:"dx","di");
return __res-cs;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~11: ct์ ๊ธธ์ด๋ฅผ ๊ตฌํ์ฌ edx์ ์ ์ฅ.
Line 12~14: esi์์ 1๋ฐ์ดํธ๋ฅผ ์ฝ๊ณ al์ ์ ์ฅ, NULL์ธ์ง ํ์ธ
Line 15~19: ct ์ค al๊ณผ ์ผ์นํ๋ ๋ฐ์ดํธ๊ฐ ์๋์ง ํ์ธ, ์๋ค๋ฉด ๋ฆฌํดํ๋ค.
Line 20: ์ผ์นํ๋ ๋ฌธ์๊ฐ ์๋ค๋ฉด(jne) 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ ๋ค์ ๋ฌธ์๋ฅผ ๋น๊ตํ๋ค.
static inline char * strpbrk(const char * cs,const char * ct)
{
int d0, d1;
register char * __res __asm__("si");
__asm__("cld\n\t"
"movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t"
"movl %%ecx,%%edx\n"
"1:\tlodsb\n\t"
"testb %%al,%%al\n\t"
"je 2f\n\t"
"movl %6,%%edi\n\t"
"movl %%edx,%%ecx\n\t"
"repne\n\t"
"scasb\n\t"
"jne 1b\n\t"
"decl %0\n\t"
"jmp 3f\n"
"2:\txorl %0,%0\n"
"3:"
:"=S" (__res), "=&a" (d0), "=&c" (d1)
:"1" (0),"2" (0xffffffff),"0" (cs),"g" (ct)
:"dx","di");
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~11: ct์ ๊ธธ์ด๋ฅผ ๊ตฌํ์ฌ edx์ ์ ์ฅ.
Line 12~14: esi์์ 1๋ฐ์ดํธ๋ฅผ ์ฝ๊ณ al์ ์ ์ฅ, NULL์ธ์ง ํ์ธ
Line 15~19: ct ์ค al๊ณผ ์ผ์นํ๋ ๋ฐ์ดํธ๊ฐ ์๋์ง ํ์ธ, ์๋ค๋ฉด ์ฐพ์ ์ฃผ์๋ฅผ ๋ฆฌํดํ๋ค.
Line 20: ์ผ์นํ๋ ๋ฌธ์๊ฐ ์๋ค๋ฉด(jne) 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ ๋ค์ ๋ฌธ์๋ฅผ ๋น๊ตํ๋ค.
static inline char * strstr(const char * cs,const char * ct)
{
int d0, d1;
register char * __res __asm__("ax");
__asm__("cld\n\t" \
"movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
"1:\tmovl %6,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 2f\n\t" /* also works for empty string, see above */
"xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
:"=a" (__res), "=&S" (d0), "=&c" (d1)
:"0" (0),"2" (0xffffffff),"4" (cs),"g" (ct)
:"dx","di");
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~11: ct์ ๊ธธ์ด๋ฅผ ๊ตฌํ์ฌ edx์ ์ ์ฅ.
Line 12~14: ct๋ฅผ edi์ ์ธํ
, esi๋ฅผ eax์ ์ธํ
, ecx์ ๊ตฌํ ๊ธธ์ด๋ฅผ ์ ์ฅ.
Line 15~17: cs์์ ct์ ์ผ์นํ๋ ๋ฌธ์์ด์ด ์๋์ง ํ์ธ, ์๋ค๋ฉด ์ฐพ์ ์ฃผ์๋ฅผ ๋ฆฌํดํ๋ค.
Line 18~22: ๋ฌธ์์ด ๋์ ๋๋ฌํ๋ฉด, 0์ ๋ฆฌํด ์๋๋ผ๋ฉด index๋ฅผ ์ฆ๊ฐ์์ผ 1๋ฒ ๋ผ๋ฒจ๋ก ๋์๊ฐ๋ค.
static inline int strlen(const char * s)
{
int d0;
register int __res __asm__("cx");
__asm__("cld\n\t"
"repne\n\t"
"scasb\n\t"
"notl %0\n\t"
"decl %0"
:"=c" (__res),"=&D" (d0)
:"1" (s),"a" (0),"0" (0xffffffff));
return __res;
}
Line 5: DF ํ๋๊ทธ ํด๋ฆฌ์ด.
Line 6~10: s์ ๊ธธ์ด๋ฅผ ๊ตฌํ์ฌ __res์ ์ ์ฅ.