x86架构下32位的短字节(小于512个)拷贝
在/linux-2.6.38_vim/arch/x86/include/asm/string_32.h中
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"
"jz 1f\n\t"
"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;
}
实现功能:
(1)执行串传送,movsl以32位单位的,rep是由ecx决定的,其实也就是n/4,这样可以保证以4对齐的字节数会被传送掉;
(2)movl将n的值付给ecx,andl对ecx的值,只留下最低两位;jz判断若为0就跳出,否则movsb以字节为单位再次传送;
static __always_inline void *__inline_memcpy(void *to, const void *from, size_t n)
{
unsigned long d0, d1, d2;
asm volatile("rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
: "0" (n / 4), "q" (n), "1" ((long)to), "2" ((long)from)
: "memory");
return to;
}
实现功能:
(1)执行串传送,movsl以32位单位的,rep是由ecx决定的,其实也就是n/4,这样可以保证以4对齐的字节数会被传送掉;
(2)直接使用testb来判断n的第二位是否为1,是说明至少还有两字节,先使用movsw来传送掉;然后使用testb来判断n的第-位是否为1,是也要再使用movsb来传送掉;
arm体系架构没有用汇编的代码,因为编译器使之效率已经很高了
在/linux-2.6.38_vim/lib/string.c中
#ifndef __HAVE_ARCH_MEMCPY
/**
* memcpy - Copy one area of memory to another
* @dest: Where to copy to
* @src: Where to copy from
* @count: The size of the area.
*
* You should not use this function to access IO space, use memcpy_toio()
* or memcpy_fromio() instead.
*/
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
EXPORT_SYMBOL(memcpy);
#endif