【混合汇编】在汇编程序中实现内存块移动xx_memmove的子程序

在汇编程序中实现内存块移动xx_memmove的子程序

实验内容:

试编写ARM汇编程序和C语言程序,实现下面的功能:
在汇编程序中实现内存块移动xx_memmove的子程序;
参数1:源地址:
参数2:目的地址;
参数3:移动字节数;

实验步骤:

(一) 在C程序中实现compare函数

compare的功能是比较两个地址参数的大小,并被汇编程序glj_memmove调用;
代码+注释:

int compare(int src, int dest)
{//进来后篡改了R2的值,size(r2)要备份
        if(src < dest)//
            return 0;//src_dest,src在dest左边,src从后往前拷贝
        return 1;//dest_src,否则src在dest右边,src从前往后拷贝
}
(二) 使用给定的memmove_test调用汇编实现的内存块移动函数

代码+注释:

IMPORT cFun 
        IMPORT compare  ;导入compare()
        AREA asmfile, CODE, READONLY 
        EXPORT glj_memmove ;导出glj_memmove()
       ENTRY 
       
glj_memmove
    ;src=M[R[R0]]=M[0x10000FC4]="1234567890ABABABABABABABABABABABABABABABAB"
    ;dest=M[R[R1]]=M[0x10000FD8]="ABABABABABABABABABABAB" 
    ;size=R[R2]=12
    STMFD sp!,{r0-r12,lr};保存进入函数前的现场资源,保存的函数返回地址
    mov r4,r0   ;备份src
    mov r5,r1   ;备份dest
    mov r6,r2   ;备份size
    bl compare
    cmp r0,#0
    mov r0,r4   ;恢复src
    mov r1,r5   ;恢复dest
    mov r2,r6   ;恢复size
    beq src_dest    ;src<dest 考虑重叠 src从后往前拷贝
    bne dest_src    ;src>dest 无所谓重叠 src从前往后拷贝
    
src_dest
    ;先判断src,dest是否4字节对齐
    ;再判断size是否为4字节对齐
    mvn r8,#3       ;r8=~0b0011=0b1100
    bics r7,r0,r8   ;r7=src&(~0b1100) 保留后两位,与上0x03不是同样的效果?
    bics r7,r1,r8   ;r7=dest&(~0b1100) 保留后两位
    movne r8,#0     ;此时r8作为标志位,ne满足则r8清零
    bne src_dest_1  ;低两位不为0,说明不是4字节对齐
    bics r7,r2,r8   ;r7=size&(~0b1100) 保留后两位即为需要1字节拷贝的size
    beq src_dest_4  ;若r7=0即没有,则只用四字节拷贝即可 
    bne src_dest_1  ;r7不为0,需要1字节拷贝
    
src_dest_4
    sub r2,r2,#4    ;r2=r2-4,为后面计算ldr末起始地址服务
    add r0,r0,r2    ;r0=src+size-4
    add r1,r1,r2    ;r1=dest+size-4
    add r2,r2,#4    ;恢复r2 size
    
src_dest_loop_4     ;注:size非4对齐,末地址也不对齐,可以先一字节搬运,当
    ldr r4,[r0],#-4 ;用r4来搬运内存数据(按字),搬完地址-4
    str r4,[r1],#-4 ;最后的时候r0,r1多减了4
    subs r2,r2,#4   ;统计剩余字节数
    bgt src_dest_loop_4 ;还有size,继续重复搬运
    b out           ;否则,搬完结束,退出子程序
    
src_dest_1  ;可以分支也可以不分,不分就重写一个;方便起见干脆重写一个src_dest_1_all
    sub r2,r2,#1    ;r2=r2-1,为后面计算末地址服务 
    add r0,r0,r2    ;r0=src+size-1      0+10-1=9
    add r1,r1,r2    ;r1=dest+size-1
    add r2,r2,#1    ;恢复r2 size
    cmp r8,#0
    beq src_dest_loop_1_all ;r7!=0
    mov r8,r7       ;备份r7
    
src_dest_loop_1_4
    ldrb r4,[r0],#-1;
    strb r4,[r1],#-1;结束后r0,r1修正+1 -> ldr -4
    ;mov r8,r7      ;这玩意不能放循环里,这里r8没用了可以被覆盖,但r7原值后面还有用,先备份      
    subs r7,r7,#1   ;r7递减计数; 10-8=2; 2-1-1=0; src -> 9-1-1=7  r0,r1修正+1 -> ldr -4这里r8没用了,可以被覆盖
    ;sub r2,r2,#1   ;同步更新剩余的字节数,多此一举了(这里没法设标志位,否则后面害得cmp)
    bne src_dest_loop_1_4
    add r0,r0,#1    ;src地址修正为实际末地址+1
    add r1,r1,#1    ;dest同上
    sub r0,r0,#4    ;
    sub r1,r1,#4
    subs r2,r2,r8   ;更新剩余的字节数
    beq out
    b src_dest_loop_4   ;修正好,直接进入循环就可
    
src_dest_loop_1_all
    ldrb r4,[r0],#-1
    strb r4,[r1],#-1
    sub r2,r2,#1
    bne src_dest_loop_1_all
    b out
    
dest_src
    mvn r8,#3       ;r8=~0b0011=0b1100
    bic r7,r0,r8    ;r7=src&(~0b1100) 保留后两位
    bic r8,r1,r8    ;r7=dest&(~0b1100) 保留后两位
    orrs r7,r7,r8 
    bgt dest_src_loop_1;正序不对齐先41
    
dest_src_loop_4
    ldr r4,[r0],#4  
    str r4,[r1],#4
    sub r2,r2,#4    ;统计剩余字节数
    cmp r2,#4       ;看看剩余字节数是否有4个,若有则正常运行,若无则跳转1字节move
    bpl dest_src_loop_4 ;还有size,继续重复搬运
    subs r2,r2,#0   ;r2<4,再看r2是否为0,同时更新剩余size
    beq out
    sub r0,r0,#4    ;地址修正
    sub r1,r1,#4
    
dest_src_loop_1     ;r2不为0,继续1字节move
    ldrb r4,[r0],#1 ;!!!
    strb r4,[r1],#1 ;!!!
    subs r2,r2,#1
    bgt dest_src_loop_1
    b out
    
out
    LDMFD sp!,{r0-r12,pc};恢复进入函数前的现场资源,把先前保存的函数返回地址传给pc
    end

(三) 调试查看结果(debug-watch)

在这里插入图片描述
可通过所有测试。

(四) 结果分析

在这里插入图片描述
个人制作,仅供参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值