memcopy()函数c语言实现和汇编实现比较

今天突然心血来潮想起我前一家公司面试时遇到的一个面试题,就是实现个memcopy()函数。当初太紧张(刚毕业第二次面试),所以写的不是很好(可以说漏洞百出);现在刚学了点汇编,刚好就用两种语言实现下;

首先来看汇编实现的memcpy函数,是利用宏函数来实现的,用汇编指令rep和movsb配合循环把数据以字节为单位从ds:esi传送到es:edi中,把循环次数放在ecx中。当然这样拷贝的才是真正的内存拷贝,其他的函数都稍微有点牵强。

#define myMemcpy(dest, src, n) ({\void* _ret = dest;\__asm__("cld;rep;movsb"\::"D"((long)(_ret)), "S"((long)(src)), "c"((long)(n)));\_ret;}) 在调试汇编实现的memcpy函数时,遇到个错误,这里记录下来:

错误:myMemcpy.c: In function ‘main’: myMemcpy.c:15: error: can’t find a register in class ‘CREG’ while reloading ‘asm’ myMemcpy.c:15: error: ‘asm’ operand has impossible constraints

发生这个错误是因为,,我开始添加了 修改寄存器列表那一栏(添加了变更寄存器si, di, ex);查了下资料说是同一个变量两次出现时使用了同一个寄存器,就会报这样的错误。解决办法是把变更寄存器中那些寄存器名称用占位符替代(di==0;si==1;cx==2);但是还是不行,后来我干脆就把 修改寄存器列表 删了,因为我记得有些gcc编译器对于在输入输出中出现过的寄存器,不列入变更寄存器列表中;(我前几篇blog中也提到在输入输出中出现过的寄存器,不用添加到变更寄存器列表中去)但是有些版本的gcc却需要添加到变更寄存器那一栏;

下面来看下c语言方式来实现memcpy函数,其实我感觉c语言来实现还是比较简单的,就是把输入的数据强制转换成字符来操作,因为在c语言中没有比字符更小的单位了。而对于是否返回ret,如果要多次使用memcpy的话( myMemcpy1(xxx, myMemcpy1(xx, xx, xx), xx) ),那肯定是要返回的。如果不需要就没必要和原来的memcpy()一样,不要太死板(不过还是建议要返回ret,可以考虑以后扩展)。

void* myMemcpy1(void* dest, void* src, unsigned int n) {char* d = (char*)dest;char* s = (char*)src;char* ret = d;while(n–){*d++ = *s++;}return ret; } 好了,该实现的都实现了,现在来测试下,当然我调试通过了,感兴趣的可以试着调试下。

int main(void) {char test1[] = "yuzhihui";char test2[1024] = {};char test3[1024] = {};myMemcpy(test2, test1, sizeof(test1));myMemcpy1(test3, test1, sizeof(test1));printf("test1:%s\n", test1);printf("test2:%s\n", test2);printf("test3:%s\n", test3);int t1 = 100;int t2 = 0;int t3 = 0;myMemcpy(&t2, &t1, sizeof(t1));myMemcpy1(&t3, &t1, sizeof(t1));printf("t1:%d\n", t1);printf("t2:%d\n", t2);printf("t3:%d\n", t3);return 0; } 下面就贴下运行的结果:

转载请注明作者和原文出处,原文地址:

如果有什么不正确之处,欢迎大家指正,一起努力,共同学习!!

长江后浪催前浪,一辈新人换旧人。

memcopy()函数c语言实现和汇编实现比较

相关文章:

你感兴趣的文章:

标签云: