zoukankan      html  css  js  c++  java
  • LDMIA、LDMIB、LDMDB、LDMDA、STMIA、LDMFD、LDMFA、LDMED、LDMEA指令详解

    ARM指令中多数据传输共有两种:

    LDM:(load  much)多数据加载,将地址上的值加载到寄存器上【读内存,写入多个寄存器

    STM:(store much)多数据存储,将寄存器的值存到地址上【把多个寄存器的值写入内存

    主要用途:现场保护、数据复制、参数传送等,共有8种模式(前面4种用于数据块的传输,后面4种是堆栈操作)如下:

    (1)IA:(Increase After) 每次传送后地址加4,其中的寄存器从左到右执行,例如:STMIA R0,{R1,LR} 先存R1,再存LR

    (2)IB:(Increase Before)每次传送前地址加4,同上

    (3)DA:(Decrease After)每次传送后地址减4,其中的寄存器从右到左执行,例如:STMDA R0,{R1,LR} 先存LR,再存R1

    (4)DB:(Decrease Before)每次传送前地址减4,同上

    (5)FD:  满递减堆栈 (每次传送前地址减4)

    (6)FA:  满递增堆栈 (每次传送后地址减4)

    (7)ED:  空递减堆栈 (每次传送前地址加4)

    (8)EA:  空递增堆栈 (每次传送后地址加4)

    注意:其中在数据块的传输中是STMMDB和LDMIA对应,STMMIA和LDMDB对应

    而在堆栈操作是STMFD和LDMFD对应,STMFA和LDMFA对应

    格式:

    LDM{cond}  mode  Rn{!}, reglist{^}

    STM{cond}  mode  Rn{!}, reglist{^}

    其中

    Rn:基址寄存器,装有传送数据的起始地址,Rn不允许为R15;

    !:表示最后的地址写回到Rn中;

    reglist:可包含多于一个寄存器范围,用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大顺序排列;

    ^:不允许在用户模式和系统模式下运行

    数据块的传输-实例:


    Ldr R1,=0x10000000          //传送数据的起始地址0x10000000     

    LDMIB R1!,{R0,R4-R6}      //从左到右加载,相当于 LDR R0,10000004  LDR R4,10000008... ...

    /*传送前地址加+4,

    所以地址加4,R0=0X1000004地址里的内容,

    地址加4,R4=0X10000008地址里的内容,

    地址加4,R5=0X1000000C地址里的内容,

    地址加4,R6=0X10000010 地址里的内容,

    由于!, 最后的地址写回到R1中,R1=0X10000010   */


    Ldr R1,=0x10000000          //传送数据的起始地址0x10000000       

    LDMIA R1!,{R0,R4-R6}         //从左到右加载,相当于 LDR R0,10000000  LDR R4,10000004... ...

    /*传送后地址加+4,

    所以R0=0X10000000地址里的内容,地址加4,

    R4=0X10000004地址里的内容,地址加4,

    R5=0X10000008地址里的内容,地址加4,

    R6=0X1000000C 地址里的内容,地址加4,

    由于!,最后的地址写回到R1中,所以R1=0X10000010   */


    LDR R1,=0x10000000          //传送数据的起始地址0x10000000        

    LDR R4,=0X10

    LDR R5,=0X20

    LDR R6,=0X30

    STMIB R1,{R4-R6}          //从左到右加载,相当于STR [R4],0X10000004    STR [R5],0X10000008 .....

    /*传送前地址加+4,所以0X10000004地址=0X10,0X10000008地址=0X20,0X1000000C地址=0X30 */


    Ldr R1,=0x10000000        //传送数据的起始地址0x10000000  

    LDR R4,=0X10

    LDR R5,=0X20

    LDR R6,=0X30

    STMIA R1!,{R4-R6 }

    /*传送后地址加+4,所以0X10000000地址=0X10,0X10000004地址=0X20,0X10000008地址=0X30,由于!,最后的地址写回到R1中,所以R1=0X1000000C  */


    中断实例(利用STMDB和LDMIA保护现场,然后通过LR寄存器返回

    1.先设置栈sp,用于后面使用stmdb存储寄存器数据

    2.当产生异常时,便进入中断:

    sub lr, lr, #4  

    //首先将lr-4,因为arm流水线,lr=当前pc+8,由于pc+4段没有执行,所以lr=(当前pc+8)-4; stmdb   sp!,    { r0-r12,lr }  

    //每次传送前-4,且从右往左存储寄存器

    //所以sp-4=lr,sp-8=r12,... sp-56=r0; 由于!,所以最后的地址写回到sp中,sp=sp-56;

    ldr lr, =int_return  //设置返回地址

    ldr pc, =EINT_Handle            //进入中断服务函数,如果中途返回就会调用pc=lr,即可执行int_return;

    int_return: ldmia   sp!,    { r0-r12,pc }^  

    //每次传送后+4,且从左往右加载数据到寄存器

    //所以r0=sp, r1=sp+4,...pc=sp+52;由于!,所以最后地址写回到sp中,sp=sp+56;

    //此时,sp=sp+56就等于最初栈顶值,pc=lr,然后返回到异常发生前的相应位置继续执行。

    //^  ^表示将spsr的值复制到cpsr,因为异常返回后需要恢复异常发生前的工作状态

  • 相关阅读:
    解析form表单数据
    linux下开启https
    Jquery UI的日历控件datepicker限制日期(转)
    [MicroPython]TPYBoardv102超全DIY案例一览
    [MicroPython]TurnipBit开发板DIY自动浇水系统
    [MicroPython]TurniBit开发板旋转按钮控制脱机摆动
    [MicroPython]TurniBit开发板DIY自动窗帘模拟系统
    [Micropython]TPYBoard v102 DIY照相机
    python的各种推导式(列表推导式、字典推导式、集合推导式)
    管理 python logging 日志使用
  • 原文地址:https://www.cnblogs.com/cxl-93/p/11014536.html
Copyright © 2011-2022 走看看