Á¦ ¸ñ:[°­ÁÂ] ÀζóÀÎ ¾î¼Àºí¸®¸¦ ºÐ¼®ÇÏÀÚ. (5) °ü·ÃÀÚ·á:¾øÀ½ [573] º¸³½ÀÌ:Çѵ¿ÈÆ (ddoch ) 1997-02-20 19:24 Á¶È¸:588 2.15 memcpy ÀÌÁ¦ ºÎÅÍ´Â ÀÛÀº °Í ¸î °³¸¸ º¸¸é ³¡³¯ °ÍÀÌ´Ù. Ǫ±ÙÈ÷ ¸¶À½À» °¡ Áö°í ¿©À¯ÀÖ°Ô »ìÆìº¸µµ·Ï ÇÏÀÚ. ±æ¾îºÁ¾ß 10ÁÙÂ¥¸® µéÀÌ´Ù. --------------------------------------------------------------------- extern inline void * __memcpy(void * to, const void * from, size_t n) { __asm__ __volatile__( "cld\n\t" "rep ; movsl\n\t" "testb $2,%b1\n\t" "je 1f\n\t" "movsw\n" "1:\ttestb $1,%b1\n\t" "je 2f\n\t" "movsb\n" "2:" : /* no output */ :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from) : "cx","di","si","memory"); return (to); } ---------------------------------------------------------------------- memcpy ´Â Àß ¾Æ½Ã´Ù½ÃÇÇ from¿¡¼­ to·Î n¹ÙÀÌÆ®¸¦ ¸Þ¸ð¸® º¹»çÇÑ´Ù. * output memory º¹»ç À̹ǷΠ¹Ýȯ°ªÀº ¾ø´Ù. * input "q"´Â ax, bx, cx, dx Áß ÇϳªÀÇ ·¹Áö½ºÅÍ¿¡ 'n'ÀÇ °ªÀ» ÇÒ´çÇÏ°Ú ´Ù°í ÄÄÆÄÀÏ·¯¿¡°Ô ÀÏ·¯ÁÖ´Â °ÍÀÌ´Ù. ecx¿¡ n/4¸¦, "q"¿¡ nÀ», edi¿¡ (long)to¸¦, esi¿¡ (long)fromÀ» °¢±â °ªÀ» Àü´ÞÇÑ´Ù. (long)°ú °°ÀÌ Æ¯Á¤ÇÏ°Ô ÇüÀ» º¯È¯ÇÔÀ¸·Î½á ±× Å©±â¿¡ µû¸¥ ·¹Áö½ºÅÍ(¿©±â¿¡¼­´Â ediµî..)À» »ç¿ëÇÒ ¼ö ÀÖ´Ù. to´Â º¹»çµÉ °÷À̹ǷΠdest index¿¡ ³Ö¾îµÎ°í, fromÀº º¹»çÇÒ °÷ À̹ǷΠsource index¿¡ °ªÀ» ÀúÀåÇÏ¿© ÀÌÈÄ¿¡ ¹®ÀÚ¿­ °ü·Ã ¸í·É À» »ç¿ëÇÏ¿© ¿øÇÏ´Â ÀÛ¾÷À» ÇÒ ¼ö ÀÖ´Ù. * commands rep; movsl°ú °°ÀÌ ¸í·ÉµéÀ» ';'·Î ºÐ¸®ÇÏ¿© ÇÑÁÙ¿¡ ÀûÀ» ¼öµµ ÀÖ´Ù. ÀÌ ¸í·É¿¡ ÀÇÇØ esi(from)¿¡¼­ edi(to)·Î n/4¸¸Å­ º¹»çµÈ´Ù. Çѹø º¹»çµÉ ¶§´Â 4¹ÙÀÌÆ®(movsl-long)¾¿ µÇ¹Ç·Î ¸¸ÀÏ nÀ» 15·Î ÁÙ °æ¿ì´Â 4ÀÇ ¹è¼öÀÎ 12¸¸Å­ º¹»çµÇ°í 3¹ÙÀÌÆ®°¡ ³²°Ô µÈ´Ù. ÀÌ·¸°Ô 4¹ÙÀÌÆ® ´ÜÀ§·Î º¹»çÇÏ´Â °ÍÀÌ 4¹ÙÀÌÆ®°¡ ±âº» µ¥ÀÌŸ ÇüÀÎ 32ºñÆ® ¿î¿µÃ¼Á¦ ¿¡¼­ ´õ È¿À²¼ºÀÌ ÁÁÀº ¸ð¾çÀÌ´Ù. ³ª¸ÓÁö 3¹ÙÀÌÆ®´Â µÚ¿¡¼­ º¹»ç¸¦ ÇÑ´Ù. Áß°£¿¡ %b1(%bl-%BL°ú È¥µ¿ÇÏÁö ¸»¶ó)ÀÌ ÀÖ´Â µ¥ À̰ÍÀº ¾Æ¸¶µµ %1+ byte ÀÇ Àǹ̰°´Ù. Áï, %1Àº nÀÇ °ªÀ̹ǷΠtestb $2, %b1Àº nÀÇ ÇÏÀ§ 1¹ÙÀÌÆ®¿Í »ó¼ö 2¸¦ & ¿¬»êÀ» ÇÑ´Ù´Â À̾߱â·Î ÇØ¼®Çϸé Á¤È®ÇÒ °Í°° ´Ù. 15¹ÙÀÌÆ® ÀÏ °æ¿ì¸¦ ¿¹·Î µé¸é, 15 : 1111 2 : 0010 & ----------- 0010 Áï, ÀÌ ¿¬»êÀº nÀÇ 2¹øÂ° ºñÆ®°¡ 1ÀÎÁö¸¦ °Ë»çÇÑ´Ù. 0À̶ó¸é 1ù¹øÂ° ºñÆ®¸¦ °Ë»çÇÏ´Â 1f·Î °¡°í, 1À̶ó¸é 2ºñÆ®¸¦ º¹»ç¸¦ Çϰí 1¹øÂ° ºñÆ® ¸¦ testb $1, %b1°ú °°ÀÌ °Ë»çÇÏ¿© 1À̸é 1¹ÙÀÌÆ®¸¦ ´õ º¹»çÇϰí, 0ÀÌ ¸é Á¾·áÇÑ´Ù. ¾ÆÁÖ ½±°Ô ÀÌÇØ°¡ µÉ °ÍÀÌ´Ù. À̹ø¿¡´Â ¾ÆÁÖ Àç¹ÌÀÖ´Â ·çƾÀÌ´Ù. ÀζóÀÎ ¾î¼Àºí¸®¸¦ ¾î¶»°Ô C ¿¡¼­ define ÇØ¼­ »ç¿ëÇÒ ¼ö ÀÖ´Â ÁöÀÇ ÇϳªÀÇ ¿¹·Î¼­ Èï¹Ì·Ó°Ô »ìÆìº¸ÀÚ. ----------------------------------------------------------------------- /* * This looks horribly ugly, but the compiler can optimize it totally, * as the count is constant. */ extern inline void * __constant_memcpy(void * to, const void * from, \ size_t n) { switch (n) { case 0: return to; case 1: *(unsigned char *)to = *(const unsigned char *)from; return to; case 2: *(unsigned short *)to = *(const unsigned short *)from; return to; case 3: *(unsigned short *)to = *(const unsigned short *)from; *(2+(unsigned char *)to) = *(2+(const unsigned char *)from); return to; case 4: *(unsigned long *)to = *(const unsigned long *)from; return to; } #define COMMON(x) \ __asm__("cld\n\t" \ "rep ; movsl" \ x \ : /* no outputs */ \ : "c" (n/4),"D" ((long) to),"S" ((long) from) \ : "cx","di","si","memory"); switch (n % 4) { case 0: COMMON(""); return to; case 1: COMMON("\n\tmovsb"); return to; case 2: COMMON("\n\tmovsw"); return to; case 3: COMMON("\n\tmovsw\n\tmovsb"); return to; } #undef COMMON } ---------------------------------------------------------------------- ¸®´©½º Åä¹ßÁî Àڽŵµ À̹ø ·çƾÀº ¸ø»ý°å´Ù°í ¸»Çϰí ÀÖ´Â µíÇÏ´Ù. C ÀÇ case ¹®Àº nÀÌ 0ÀÏ ¶§´Â ±×³É ¸®ÅÏÇϰí, 1,2,3À϶§´Â unsigned char *, unsigned short *,·Î void *¸¦ Çüº¯È¯ÇÏ¿© Æ÷ÀÎÅ͸¦ »ç¿ëÇÏ¿© °ªÀ» ±×´ë·Î ¸Þ¸ð¸®·Î Àû°í ÀÖ´Ù. void *ÀÇ À¯¿ëÇÑ Á¡Àº ¾î¶°ÇÑ Æ÷ÀÎÅÍ ÇüÀ¸·Îµµ º¯È¯µÉ ¼ö ÀÖ´Ù´Â µ¥ ÀÖ´Â µ¥, À̰ÍÀ» Àß È°¿ëÇϰí ÀÖ´Â ¼ÀÀÌ´Ù. from°ú to¸¦ *(unsigned char *)·Î °ªÀ» Àû´Â ´Ù¸é ÇØ´çÇÏ´Â °÷¿¡ 1¹ÙÀÌÆ®¸¦ Àû°Ô µÇ°í *(unsigned short *)·Î ÃëÇϸé 2¹ÙÀÌÆ®¸¦ Àû°Ô µÈ´Ù. ´ç¿¬È÷ unsigned long À» ÃëÇϸé 4¹ÙÀÌÆ®¸¦ Àû°Ô µÈ´Ù. ÀÌ °æ¿ìÀÇ Æ÷ÀÎÅÍ¿¡ 1,2,3 µîÀÇ ¿¬»êÀº ±× ¾î¶°ÇÑ Æ÷ÀÎÅÍ·Î ÇØ´çÇÏ´Â ÁÖ¼Ò°¡ ÂüÁ¶µÇ¾ú´À³Ä¿¡ µû¶ó¼­, Áõ°¡ÇÏ´Â ÆøÀÌ ´Þ ¶óÁø´Ù. const´Â fromÀÌ °¡¸£Å°°í ÀÖ´Â °÷ÀÇ µ¥ÀÌŸ¸¦ »ó¼öÇüÅ·ΠÃë±ÞÇÔÀ¸ ·Î½á º¯°æÀ» ±ÝÁöÇÔÀ» ÄÄÆÄÀÏ·¯¿¡°Ô ¾Ë¸®°í ÀÖ´Ù. ¸¶Âù°¡Áö·Î 8,12...20°ú °°ÀÌ ÀûÀº ¼ö¿¡´Â ±×³É ¹Ù·Î Æ÷ÀÎÅÍ ¿¬»êÀ¸·Î °ªÀ» º¹»çÇÑ´Ù. COMMONÀº ¿©±â¿¡¼­ ƯÁ¤ºÎºÐ¿¡¸¸ Á¤ÀǵȴÙ. ÀζóÀÎ ¾î¼À¿¡¼­ °øÅëµÇ´Â ºÎºÐ À» µû·Î ºÐ¸®ÇÏ¿© Á¤ÀÇÇÑ °ÍÀÌ´Ù. ³»ºÎÀÇ ÀζóÀÎ ¾î¼ÀÀ» º¸¸é.. ecx¿¡ n/4¸¦, edi¿¡ to¸¦, esi¿¡ fromÀ» Àü´ÞÇϰí ÀÖ´Ù. cld; rep; movsl; ·Î ÀÎÇÏ¿© n/4¸¸Å­ from¿¡¼­ to·Î 4¹ÙÀÌÆ® ´ÜÀ§·Î º¹»ç¸¦ ÇÑ´Ù. ³ª¸ÓÁö ³²Àº ¿©ºÐÀÇ 1-3¹ÙÀÌÆ®´Â define À» ÀûÀýÈ÷ Ȱ¿ëÇÑ´Ù. COMMAN("\n\tmovsb")´Â À§ÀÇ define¿¡ ÀÇÇØ __asm__("cld\n\t" \ "rep; movsl" \ "\n\tmovsb" \ : .. ..... ); ·Î ÇØ¼®ÀÌ µÈ´Ù. ³ª¸ÓÁöÀÇ °æ¿ìµµ n%4¹ÙÀÌÆ® ¸¸Å­ º¹»ç¸¦ Çϱâ À§ÇÏ¿© define À» Ȱ¿ëÇÑ´Ù. 2.16 memmove memmove´Â src¿¡¼­ dest·Î n¹ÙÀÌÆ®¸¸Å­À» ¸Þ¸ð¸® À̵¿À» ½ÃŰ´Â °ÍÀÌ´Ù. memcpy¿Í °ÅÀÇ ºñ½ÁÇÏ´Ù°í º¼ ¼ö ÀÖÀ¸³ª src¿Í dest°¡ °ãÄ¡´Â °æ¿ì¸¦ ´ëºñÇÏ¿© Á¤»óÀûÀÎ °ªÀ» º¹»çÇÑ´Ù´Â Á¡¿¡¼­ Á¶±Ý Â÷À̰¡ ÀÖ´Ù. -------------------------------------------------------------------- extern inline void * memmove(void * dest,const void * src, size_t n) { if (dest__asm__ __volatile__( "cld\n\t" "rep\n\t" "movsb" : /* no output */ :"c" (n),"S" (src),"D" (dest) :"cx","si","di"); else __asm__ __volatile__( "std\n\t" "rep\n\t" "movsb\n\t" "cld" : /* no output */ :"c" (n), "S" (n-1+(const char *)src), "D" (n-1+(char *)dest) :"cx","si","di","memory"); return dest; } --------------------------------------------------------------------- ¸ñÀûÁö ÁÖ¼Ò < ¿øÃµÁö ÁÖ¼Ò ÀÏ °æ¿ì¿Í, ¸ñÀûÁö ÁÖ¼Ò >= ¿øÃµÁö ÁÖ¼Ò ÀÏ °æ¿ì·Î ³ª´©¾î ó¸®Çϰí ÀÖ´Ù. ÀϹÝÀûÀ¸·Î µÎ°³ÀÇ ¿µ¿ªÀÌ °ãÄ¡Áö ¾Ê´Â´Ù¸é º° ¹®Á¦ ¾øÀÌ Ã³¸®µÇÁö¸¸ °ãÄ¡´Â °æ¿ì¸¦ ¿¹·Î µé¾îº¸ÀÚ. ´ÙÀ½°ú °°ÀÌ ±×¸²À» ±×·Áº¸¸é, (1) dest < src <------ low address high address ------------> dest ¿µ¿ª -------------------------+ | +-------------------------------------------------------------+ | dest ¿µ¿ª | °ãÄ¡´Â ¿µ¿ª | src ¿µ¿ª | +-------------------------------------------------------------+ abcdefg.... |12345..... +--------------------- src ¿µ¿ª ÀÌ °æ¿ì¿¡´Â srcÀÇ 12345ºÎÅÍ Â÷·Ê´ë·Î destÀÇ abcdef...·Î º¹»ç¸¦ ÇØ ÁÖ¸é º° ÀÌ»ó¾ø´Ù. ecx¿¡´Â n, esi¿¡´Â src, edi¿¡´Â dest°¡ Àü´ÞµÇ¾î cld; rep; movsb;·Î Á¤¹æÇâÀ¸·Î src¿¡¼­ dest·Î n¸¸Å­ ¹ÙÀÌÆ® º¹»ç¸¦ ÇÏ°Ô µÈ´Ù. (2) src <= dest <------ low address high address ------------> src ¿µ¿ª -------------------------+ | +-------------------------------------------------------------+ | src ¿µ¿ª | °ãÄ¡´Â ¿µ¿ª | dest ¿µ¿ª | +-------------------------------------------------------------+ 12345... |abcde.. ..789 ...xyz +--------------------- dest ¿µ¿ª ÀÌ °æ¿ì¿¡´Â 12345...(src)¿¡¼­ abcde..(dest)·Î ¹Ù·Î º¹»ç¸¦ ÇØ¹ö¸° ´Ù¸é º¹»ç¸¦ ä ´ÙÇϱ⵵ Àü¿¡ srcÀÇ µÞºÎºÐÀÇ °ªÀÌ º¯°æµÇ¾î ¹ö·Á¼­ Á¤»óÀûÀÎ º¹»ç°¡ ÀÌ·ç¾î ÁöÁö ¾ÊÀ» °ÍÀÌ´Ù. À̶§¿¡´Â srcÀÇ µÞºÎºÐÀÎ 9,8,7 ºÎÅÍ destÀÇ µÞºÎºÐÀÎ z,y,x·Î º¹»ç¸¦ °Å²Ù·Î Çϸé Á¤»óÀûÀÎ º¹ »ç¸¦ ÇÒ ¼ö ÀÖ´Ù. ecx¿¡ n, esi¿¡ (n-1+(const char *)src)¸¦, edi¿¡ (n-1+(char *)dest )¸¦ °¢°¢ Àü´ÞÇϰí ÀÖ´Ù. Áï, src, dest¿¡¼­ n¸¸Å­À» ´õÇÑ ÁÖ¼Ò¸¦ °¡ ¸£Å²´Ù. std; rep; movsb·Î À̹ø¿¡´Â °Å²Ù·Î srcÀÇ µÞºÎºÐ¿¡¼­ dest ÀÇ µÞºÎºÐÀ¸·Î ¹ÙÀÌÆ® ¸Þ¸ð¸® º¹»ç°¡ n¹ø ÀÌ·ç¾îÁø´Ù. 2.17 memchr memchrÀº strchrÀÇ ¸Þ¸ð¸® ¹öÁ¯ÀÌ´Ù. --------------------------------------------------------------- extern inline void * memchr(const void * cs,int c,size_t count) { register void * __res; if (!count) return NULL; __asm__ __volatile__( "cld\n\t" "repne\n\t" "scasb\n\t" "je 1f\n\t" "movl $1,%0\n" "1:\tdecl %0" :"=D" (__res):"a" (c),"D" (cs),"c" (count) :"cx"); return __res; } ----------------------------------------------------------------- cs°¡ °¡¸£Å°´Â ¸Þ¸ð¸®¿¡¼­ ½ÃÀÛÇÏ¿© cÀÇ °ªÀÌ ÀÖ´ÂÁö¸¦ count¹ø °Ë»ç ¸¦ ÇÑ´Ù. outputÀº edi·Î ÅëÇØ¼­ __res·Î °á°ú°ªÀÌ Àü´ÞµÇ°í,inputÀº eax¿¡ ã°íÀÚÇÏ´Â °ª c¸¦, edi¿¡ cs¸¦, ecx¿¡ count¸¦ °¢°¢ Àü´ÞÇϰí ÀÖ´Ù. ¸ÕÀú C¿¡¼­ void * __res¸¦ ¼±¾ðÀ» Çϰí count°¡ 0À̶ó¸é NULL À» ¸®ÅÏÇÑ´Ù. ¾Æ´Ï¶ó¸é ¾î¼Àºí¸® ·çƾÀ» ½ÇÇàÇÑ´Ù. eax¿¡´Â int aÀÇ °ªÀÌ µé¾î°¡ ÀÖÀ¸³ª »ç½Ç»óÀº eaxÀÇ ÇÏÀ§ 1¹ÙÀÌÆ®ÀÎ al¸¸ÀÌ °Ë»ç¸¦ À§Çؼ­ »ç¿ëµÈ´Ù. cld; repne; scasb; ´Â ecx(count) ¹ø al(aÀÇ ÇÏÀ§1¹ÙÀÌÆ®)ÀÇ °ª°ú edi(cs)°ªÀ» ºñ±³ÇÏ¿© °°Áö ¾Ê´Ù¸é °è¼Ó ¹Ýº¹ÇÏ¿© °°Àº °ªÀÌ ³ª¿À¸é ±× ´ÙÀ½À» edi°¡ °¡¸£Å²´Ù. µû¶ó¼­ ¹ß°ßÇÑ´Ù¸é je 1f·Î decl %%edi¸¦ ÇÏ¿© Çϳª¸¦ °¨¼Ò½ÃŲ ´ÙÀ½ÀÇ ¸Þ¸ð ¸® À§Ä¡¸¦ __res·Î ³Ñ°ÜÁØ´Ù. °°Àº °ªÀ» ãÁö ¸øÇß´Ù¸é movl $1, %%edi¸¦ ÇÏ¿© edi¿¡ 1À» ÀúÀåÇϰí decl %%edi·Î 0ÀÌ µÇ¾î __res´Â NULLÆ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù. 2. 18 memset -------------------------------------------------------------- extern inline void * __memset_generic(void * s, char c, \ size_t count) { __asm__ __volatile__( "cld\n\t" "rep\n\t" "stosb" : /* no output */ :"a" (c),"D" (s),"c" (count) :"cx","di","memory"); return s; } --------------------------------------------------------------- al(eax)¿¡ c¸¦, edi¿¡ s¸¦, ecx¿¡ count¸¦ Àü´ÞÇϰí ÀÖ´Ù. cld; rep; stasb; ·Î al(c)ÀÇ °ªÀ» edi(s)°¡ °¡¸£Å°´Â °÷¿¡ ecx(count)¹ø ¹Ýº¹ ÇÏ¿© ¾´´Ù. ----------------------------------------------------------------------- /* * memset(x,0,y) is a reasonably common thing to do, so we want to fill * things 32 bits at a time even when we don't know the size of the * area at compile-time.. */ extern inline void * __constant_c_memset(void * s, unsigned long c, \ size_t count) { __asm__ __volatile__( "cld\n\t" "rep ; stosl\n\t" "testb $2,%b1\n\t" "je 1f\n\t" "stosw\n" "1:\ttestb $1,%b1\n\t" "je 2f\n\t" "stosb\n" "2:" : /* no output */ :"a" (c), "q" (count), "c" (count/4), "D" ((long) s) :"cx","di","memory"); return (s); } ----------------------------------------------------------------------- eax¿¡ unsigned long c¸¦, eax, ebx, ecx, edx Áß Çϳª¿¡ count¸¦, ecx¿¡ count/4¸¦, edi¿¡ s¸¦ Àü´ÞÇϰí ÀÖ´Ù. °ªÀ» Àü´ÞÇÒ ¶§ Àü´ÞµÇ´Â ÀÎÀÚÇüÀÇ Å©±â¿¡ µû¶ó¼­ commands±¸¹®¿¡¼­ ÀûÀýÈ÷ »ç¿ëÇÏ¿©¾ß ÇÑ´Ù. ±×·¸Áö ¾Ê´Ù¸é ¹ö±×°¡ µÉ ¼ö ÀÖÀ» °ÍÀÌ´Ù. cld; rep; stosl;·Î eaxÀÇ °ªÀ» edi(s)°¡ °¡¸£ Ű´Â °÷¿¡ 4¹ÙÀÌÆ®¾¿ ecx(count/4)¸¸Å­À» ¹Ýº¹ÇÏ¿© ¾´´Ù. ÀÌÀü¿¡ º»¹Ù¿Í ¸¶Âù°¡Áö·Î testb $2, %b1; testb $1, %b1; °ú °°Àº °ÍÀ¸·Î countÀÇ ÇÏÀ§ 2,1¹øÂ° ºñÆ®¸¦ °Ë»çÇÏ¿© °¢°¢ 2¹ÙÀÌÆ®, 1¹ÙÀÌÆ®¸¦ ax, al¿¡¼­ °¡Á®¿Í¼­ ¾²°í ÀÖ´Ù. 2.19 strnlen ---------------------------------------------------------------------- /* Added by Gertjan van Wingerde to make minix and sysv module work */ extern inline size_t strnlen(const char * s, size_t count) { register int __res; __asm__ __volatile__( "movl %1,%0\n\t" /* ecx -> eax */ "jmp 2f\n" "1:\tcmpb $0,(%0)\n\t" /* cmpb $0, [eax] */ "je 3f\n\t" "incl %0\n" /* eax++ */ "2:\tdecl %2\n\t" /* edx-- */ "cmpl $-1,%2\n\t" /* cmpl $-1, edx */ "jne 1b\n" "3:\tsubl %1,%0" /* eax -= ecx */ :"=a" (__res):"c" (s),"d" (count)); return __res; } /* end of additional stuff */ ---------------------------------------------------------------------- outputÀº eax¸¦ ÅëÇØ¼­ __res¿¡ Àü´ÞµÇ°í ÀÖ´Ù. ecx¿¡´Â s¸¦, edx¿¡´Â count ¸¦ inputÀ¸·Î Àü´ÞÇϰí ÀÖ´Ù. strnlen("abc", 3); strnlen("abc", 5); strnlen("abc", 2); ·Î ÇÏ¿© °¢°¢ È£ÃâÇϸé 3, 3, 2¸¦ ¸®ÅÏÇÑ´Ù. Áï, count¾È¿¡¼­ s¿¡¼­ ³ÎÀÌ ³ª¿À¸é ±× ±æÀÌ ¸¦ µ¹·ÁÁÖ°í ³ª¿ÀÁö ¾ÊÀ¸¸é count ¸¸Å­À» ¸®ÅÏÇÏ´Â °ÍÀÌ´Ù. cmpb $0, (%0)Àº sÀÇ º¹»çº» Æ÷ÀÎÅ͸¦ Çϳª Áõ°¡ ½Ã۰í, incl %0Àº sÁß ³Î ÀÌ ¾Æ´Ï¶ó¸é ´ÙÀ½ °÷À» °¡¸£Å°°Ô Çϸç decl %2´Â countÀÇ º¹»çº»À» Çϳª °¨ ¼Ò½ÃŰ¸é¼­ sÁß ³Î¹®ÀÚ¸¦ ¸¸³ª°Å³ª cmpl $=1, %2; ó·³ countÀÇ º¹»çº»ÀÌ -1ÀÌ µÇ¸é ÁøÇàµÈ sÀÇ º¹»çº»¿¡¼­ ¿ø·¡ sÀÇ °ªÀ» »©¼­ µ¹·ÁÁØ´Ù. À̰ÍÀº sÀÇ ¹®ÀÚ¿­ ±æÀÌÀ̰ųª countÀÌ´Ù. 2.20 etc functions ³ª¸ÓÁö ¸î°³¸¦ »ìÆìº¸ÀÚ. À̰͵µ ÀÌÀüÀÇ memset°ú °ÅÀÇ °°´Ù. ±×·¯¸é¼­µµ Á¶±Ý¾¿ ´Ù¸£°Ô ÀÛµ¿ÇÏ´Â ÇÔ¼ö°¡ ¿©·¯°³ÀÌ´Ù. ----------------------------------------------------------------------- /* * This looks horribly ugly, but the compiler can optimize it totally, * as we by now know that both pattern and count is constant.. */ extern inline void * __constant_c_and_count_memset(void * s, \ unsigned long pattern, size_t count) { switch (count) { case 0: return s; case 1: *(unsigned char *)s = pattern; return s; case 2: *(unsigned short *)s = pattern; return s; case 3: *(unsigned short *)s = pattern; *(2+(unsigned char *)s) = pattern; return s; case 4: *(unsigned long *)s = pattern; return s; } #define COMMON(x) \ __asm__("cld\n\t" \ "rep ; stosl" \ x \ : /* no outputs */ \ : "a" (pattern),"c" (count/4),"D" ((long) s) \ : "cx","di","memory") switch (count % 4) { case 0: COMMON(""); return s; case 1: COMMON("\n\tstosb"); return s; case 2: COMMON("\n\tstosw"); return s; case 3: COMMON("\n\tstosw\n\tstosb"); return s; } #undef COMMON } ----------------------------------------------------------------------- eax¿¡ patternÀ» ³Ö°í, ecx¿¡ count/4¸¦ ³Ö°í, edi¿¡ s¸¦ ³Ö´Â´Ù. ±×´ÙÀ½ count°¡ ÀûÀ» °æ¿ì¿¡´Â ±×³É ¹Ù·Î s¿¡ Á¢±ÙÇÏ¿© count ÀÇ Å©±â¿¡ µû¶ó patterns¸¦ Àû°í, Á¶±Ý Ŭ °æ¿ì¿¡´Â define Á¤ÀǸ¦ »ç¿ëÇÏ¿© ¾î¼Àºí ¸® ·çƾÀ¸·Î ó¸®ÇÑ´Ù. cld; rep; stosl; ·Î ecx¿¡ ÀúÀåµÈ Ƚ¼ö¸¸Å­ eax ÀÇ °ªÀ» edi(s)°¡ °¡¸£Å°´Â °÷¿¡ 4¹ÙÀÌÆ®¾¿À» ¾´´Ù. ±×¸®°í count%4ÀÇ °ª ¿¡ µû¶ó ¿©ºÐÀÇ ¹ÙÀÌÆ®¸¦ ¾²°Ô µÈ´Ù. À§¿¡¼­ º»¹Ù¿Í °°´Ù. À̹ø¿¡´Â memscanÀÌ´Ù. À§¿¡¼­ º» memchr°ú °ÅÀÇ ºñ½ÁÇÏ´Ù. --------------------------------------------------------------------- /* * find the first occurrence of byte 'c', or 1 past the area if none */ extern inline void * memscan(void * addr, int c, size_t size) { if (!size) return addr; __asm__("cld repnz; scasb jnz 1f dec %%edi 1: " : "=D" (addr), "=c" (size) : "0" (addr), "1" (size), "a" (c)); return addr; } ----------------------------------------------------------------------- inputÀº edi¿¡ addrÀ» , ecx¿¡ size¸¦ , eax¿¡ ãÀ» °ªÀÎ c¸¦ Àü´ÞÇÑ´Ù. outputÀº edi¸¦ ÅëÇÏ¿© addr·Î °ªÀ» Àü´ÞÇϰí, ecx¸¦ ÅëÇÏ¿© size¿¡ °ªÀ» Àü´ÞÇÑ´Ù. ¸ÕÀú size°¡ 0À̸é addrÀ» ±×³É ¸®ÅÏÇÑ´Ù. cld; repnz; scasb; ·Î al(cÀÇ ÇÏÀ§1¹ÙÀÌÆ®)ÀÇ °ª°ú edi(addr)ÀÌ °¡¸£Å°´Â °÷ÀÇ °ªÀÌ °°Àº Áö¸¦ ¹ÙÀÌÆ® ´ÜÀ§·Î ecx(size) ¹ø °Ë»çÇÏ¿© ÇÑ´Ù. ã¾Ò´Ù¸é dec %%edi·Î edi¸¦ Çϳª °¨¼Ò½ÃÄѼ­ ãÀº À§Ä¡¸¦ addr·Î Àü´ÞÇÏ°í ¸øÃ£¾Ò´Ù¸é ÇöÀç º° ÀÇ¹Ì ¾ø´Â °÷À» °¡¸£Å°°í ÀÖ´Â edi¸¦ ±×´ë·Î addr·Î Àü ´ÞÇÑ´Ù. ( ÇÏÀÌÅÚÀÌ 500¶óÀÎÀÌ ÇѰè¶ó¼­ ºÎµæÀÌ ´ÙÀ½ °Ô½Ã¹°·Î ³ª¸ÓÁö¸¦ Àû´Â´Ù.) ¾î½º¸§ÀÌ Áú³á¿¡ ddoch Çѵ¿ÈÆ µå¸²