注:参考学习,共同进步。
参考memmove源码
void* memmove(void* dst,const void* src,size_t count)
{
void* ret = dst;
//dst <= src表示,如果dst在src的前面,从前往后复制不会覆盖src中还没有复制的内容
if (dst <= src || (char*)dst >= ((char*)src + count))
{
//从前往后复制,则不会出现覆盖src中没有复制的内容
while(count--)
{
*(char*)dst = *(char*)src; //char类型指针,表示一个字节一个字节的复制
dst = (char*)dst + 1; //移动一个字节
src = (char*)src + 1;
}
}
else
{
//从后往前复制,则不会出现覆盖src中没有复制的内容
dst = (char*)dst + count - 1;//移动到末尾
src = (char*)src + count - 1;
while(count--)
{
*(char*)dst = *(char*)src;
dst = (char*)dst - 1; //移动一个字节
src = (char*)src - 1;
}
}
//返回dst的头指针,还方便左值操作。
//如:ptstr = memmove(ptstr,src,count); cout << memmove(ptstr,src,count);
return ret;
}
汇编程序段:
AREA MEMM,CODE,READONLY
EXPORT mem
IMPORT compare
mem
mov r6,lr;保存下一跳指令地址
mov r7,r0;备份目的地址
mov r5,r1;备份源地址
bl compare;调用c
cmp r0,#0;返回值比较
mov r0,r7;恢复目的地址
mov r1,r5;恢复源地址
bne M1;;跳转从前向后复制
beq M2;;跳转从后向前复制
M1;从前向后复制
L1 ;四字节拷贝
subs r2,r2,#4
ldrpl r4,[r1],#4
strpl r4,[r0],#4
bgt L1
add r2,r2,#4;因为出循环时长度减多了一次4,要加4
L2 ;一字节拷贝
subs r2,r2,#1
ldrplb r4,[r1],#1
strplb r4,[r0],#1
bgt L2
b out;;结束
M2;从后往前复制,把地址指针放到最后
sub r2,r2,#1
add r0,r0,r2
add r1,r1,r2
add r2,r2,#1
mvn r8,#3;
bic r5,r2,r8;取拷贝长度%4的余数,一字节拷贝长度
sub r2,r2,r5;剩余的4字节拷贝的长度
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
b out;结束
out;函数出口
mov r0,r7 ;返回值目的地址
mov pc,r6; 把先前保存的下一条指令地址传给pc
end
c程序段:
#include <stdio.h>
extern void* mem(void* dst,void*src,int len);
int compare(void* dst,void* src);
//extern int add(int a,int b);
int main()
{
char c[7]="dcba";
char a[7]="abcdef";
mem(c,a,7);
printf("%s",c);
return 0;
}
int compare(void* dst,void* src)
{
if(dst<=src) return 1;
else return 0;
}
运行测试:
实现了memmove函数功能(快速移动,内容非4字节对齐)