memmove函数进阶版(内容非4+地址非4对齐均可快速复制)

注:参考学习,共同进步。

普通拷贝方式:所有内容都用ldrb/strb拷贝,即1字节拷贝。

快速拷贝原理:尽可能的用4字节ldr/str指令拷贝内容,剩余的内容用1字节拷贝。

地址需要修正原因:因为ldr/str是4字节拷贝的指令,address需要是4字节对齐的才能正常加载/存储.

memmove函数拷贝时需要考虑的因素

  1. 源地址和目的地址大小的比较(内存重叠),决定前序还是后序拷贝。
  2. 源地址和目的地址地址非4,判断能不能修正地址。
  3. 1字节拷贝的三种情况:
    地址非4且不能修正;
    修正地址的部分内容用1字节拷贝;
    剩余的内容(修正地址后,或4字节拷贝结束后剩余的内容);

c测试代码:

#include <stdio.h>

extern char* mem(void* dst,void*src,int len);
int compare(void* dst,void*  src);
void test(void*array,void*dst,void*src,int len);
int main()
{
 	 char test1[30]="123456789***abcdfeghi";
 	 char test2[30]="123456789***abcdfeghi";
 	 char test3[30]="*1234567890**abcdfeghij";
 	 char test4[30]="*1234567890**abcdfeghij";
 	 char test5[30]="*******12345";
 	 char test6[30]="*12345**abcdf";
 	 
     test(test1, test1, test1+12,9);//dst<src 地址4字节对齐,内容非4测试(从前往后拷贝)
     test(test2, test2+12, test2,9);//dst>src 地址4字节对齐,内容非4测试(从后向前拷贝)  
     test(test3, test3+1, test3+13,10);//dst<src 地址非4字节对齐但可修正+内容非4测试(从前往后拷贝)
     test(test4, test4+13, test4+1,10);//dst>src 地址非4字节对齐但可修正+内容非4测试(从后向前拷贝)   
     test(test5, test5+1, test5+7,5);//dst<src 地址非4字节对齐且不可修正,内容非4测试(从前往后拷贝)  
     test(test6, test6+8, test6+1,5);//dst>src 地址非4字节对齐且不可修正,内容非4测试(从后向前拷贝)
   
     return 0;
}

int compare(void* dst,void* src)//返回值的正负代表拷贝顺序;返回+/-4代表可以4字节拷贝;返回+/-1代表地址不能修正,只能单字节拷贝
{
	int res=((int)dst-(int)src)%4;
	if (res==0){
		if(dst<=src) return -4;//前序
		else return 4;//后序
	}
	else{
		if(dst<=src) return -1;
	else return 1;
	}
}

void test(void*array,void*dst,void*src,int len)
{
	 char * const show=array;
	 printf("before:%s\n",show);
     mem( dst, src,len);//调用汇编实现的mem函数
     printf(" after:%s\n\n",show);
}

memmove功能实现的汇编代码:

     
        
    AREA MEMM,CODE,READONLY
    EXPORT mem  
    IMPORT compare	 
mem
	STMFD sp!,{r0-r12,lr};保存进入函数前的现场资源,保存的函数返回地址
	mov r9,r0;备份目的地址
	mov r7,r0;备份目的地址
	mov r5,r1;备份源地址
	mov r4,r2;备份拷贝长度
	bl compare;调用c
	mov r8,r0
	mov r0,r7;恢复目的地址
	mov r1,r5;恢复源地址
	mov r2,r4;恢复拷贝长度
	cmp r8,#-4;返回值比较跳转,共4种情况
	beq M1;地址修正后可以4字节拷贝(从前往后)的情况
	cmp r8,#4
	beq M2;地址修正后可以4字节拷贝(从后向前)的情况
	cmp r8,#-1
	beq L2;地址修正无效,只可以单字节拷贝(从前往后)的情况
	cmp r8,#1
	beq L5;地址修正无效,只可以单字节拷贝(从后向前)的情况


M1	;从前向后复制
	
	mvn r8,#3;
	bics r7,r1,r8;
	beq L1;
	rsb r7,r7,#4;修正部分
	sub r2,r2,r7
L0 ;地址修正的内容一字节拷贝
	subs r7,r7,#1
	ldrplb r4,[r1],#1
	strplb r4,[r0],#1
	bgt L0
	

L1 ;四字节拷贝
	subs r2,r2,#4 ;从前向后复制
	ldrpl r4,[r1],#4
	strpl r4,[r0],#4
	bgt L1
	add r2,r2,#4;
L2;剩余的内容一字节拷贝
	subs r2,r2,#1
	ldrplb r4,[r1],#1
	strplb r4,[r0],#1
	bgt L2
	b out
	
M2	;从后往前复制,把地址指针放到最后	
	mvn r8,#3;
	bics r7,r1,r8;修正地址
	rsbne r7,r7,#4
	
	sub r5,r2,r7 ;尾数处理
	bic r5,r5,r8
	
	sub r2,r2,#1;指针移到最后
	add r0,r0,r2
	add r1,r1,r2
	add r2,r2,#1
	sub r2,r2,r5
	
L3 ;剩余的内容一字节拷贝
	subs r5,r5,#1
	ldrplb r4,[r1],#-1
	strplb r4,[r0],#-1
	bgt L3
	sub r1,r1,#3;
	sub r0,r0,#3;

L4 	;四字节拷贝
	subs r2,r2,#4 ;从后往前复制
	ldrpl r4,[r1],#-4
	strpl r4,[r0],#-4
	bgt L4
	addmi r2,r2,#4;
	add r1,r1,#3;
	add r0,r0,#3;
	b L6
L5
	sub r2,r2,#1;指针移到最后
	add r0,r0,r2
	add r1,r1,r2
	add r2,r2,#1
L6	;地址修正的内容一字节拷贝
	subs r2,r2,#1
	ldrplb r4,[r1],#-1
	strplb r4,[r0],#-1
	bgt L6
	b out
out ;函数出口
	LDMFD sp!,{r0-r12,pc};恢复进入函数前的现场资源,把先前保存的函数返回地址传给pc  	     
    end

运行结果截图:
在这里插入图片描述
比较拷贝前后(内存重叠)的内容变化,可得memmove快速拷贝功能实现。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值