memcpy函数代码分析
memcpy调用了__memcpy函数执行内存的复制(__memcpy3d就先不管了),下面是这个这两个函数的代码
看了一本内联汇编的书,总算把这段代码搞懂了。
起始时,把n/4保存在%ecx寄存器中,并把to和from的地址分别存入%edi和%esi (引用占位符)
然后重复调用movsl n/4次,接下来应该还有(n mod 4)个字节尚未复制,这里用了一个比较巧妙的方法
movl %4, %%ecx 把n的值保存到%ecx
andl $3, %%ecx n与3做逻辑与,得到n mod 4
jz 1f 如果4 | n,跳过后面的复制
rep movsb 再复制(n mod 4)个字节
由于是按四个字节复制的,因此效率上memcpy肯定比strcpy高不少。
memcpy调用了__memcpy函数执行内存的复制(__memcpy3d就先不管了),下面是这个这两个函数的代码
void
*
memcpy(
void
*
to,
const
void
*
from, size_t n)
{
#ifdef CONFIG_X86_USE_3DNOW
return __memcpy3d(to, from, n);
#else
return __memcpy(to, from, n);
#endif
}
static __always_inline void * __memcpy( void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"movl %4,%%ecx\n\t"
"andl $3,%%ecx\n\t"
#if 1 /* want to pay 2 byte penalty for a chance to skip microcoded rep? */
"jz 1f\n\t"
#endif
"rep ; movsb\n\t"
"1:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
: "memory");
return (to);
}
{
#ifdef CONFIG_X86_USE_3DNOW
return __memcpy3d(to, from, n);
#else
return __memcpy(to, from, n);
#endif
}
static __always_inline void * __memcpy( void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
"rep ; movsl\n\t"
"movl %4,%%ecx\n\t"
"andl $3,%%ecx\n\t"
#if 1 /* want to pay 2 byte penalty for a chance to skip microcoded rep? */
"jz 1f\n\t"
#endif
"rep ; movsb\n\t"
"1:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
: "memory");
return (to);
}
看了一本内联汇编的书,总算把这段代码搞懂了。
起始时,把n/4保存在%ecx寄存器中,并把to和from的地址分别存入%edi和%esi (引用占位符)
然后重复调用movsl n/4次,接下来应该还有(n mod 4)个字节尚未复制,这里用了一个比较巧妙的方法
movl %4, %%ecx 把n的值保存到%ecx
andl $3, %%ecx n与3做逻辑与,得到n mod 4
jz 1f 如果4 | n,跳过后面的复制
rep movsb 再复制(n mod 4)个字节
由于是按四个字节复制的,因此效率上memcpy肯定比strcpy高不少。