memcpy函数代码分析
memcpy调用了__memcpy函数执行内存的复制(__memcpy3d就先不管了),下面是这个这两个函数的代码
void
*
memcpy(
void
*
to,
const
void
*
from, size_t n)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
#ifdef CONFIG_X86_USE_3DNOW
return __memcpy3d(to, from, n);
#else
return __memcpy(to, from, n);
#endif
}
![](/Images/OutliningIndicators/None.gif)
static
__always_inline
void
*
__memcpy(
void
*
to,
const
void
*
from, size_t n)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
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高不少。
memcpy调用了__memcpy函数执行内存的复制(__memcpy3d就先不管了),下面是这个这两个函数的代码
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/9b8a8a44dd1c74ae49c20a7cd451974e.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/9b8a8a44dd1c74ae49c20a7cd451974e.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
看了一本内联汇编的书,总算把这段代码搞懂了。
起始时,把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高不少。