IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> ARM base instruction -- ldm -> 正文阅读

[嵌入式]ARM base instruction -- ldm

/*
?* ldm
?*
?* 批量访问内存,内存中批量读取数据到寄存器
?*/

?? ?LDM|STM {type} 基址寄存器{!}, 寄存器列表{^}

?? ?ldm{cond} {!} < register list> {^}

?? ?批量访问内存,内存中批量读取数据到寄存器。从< rn> 对应的内存块中取出数据,写入 < register list>这些寄存器。

?? ?参数

?? ??? ?{cond}表示指定执行条件

?? ?表示内存变化的模式:

?? ??? ?ia(increment after):事后递增方式
?? ??? ?ib(increment before):事先递增方式
?? ??? ?da(decrement after):事后递减方式
?? ??? ?db(decrement before):事先递减方式

?? ?< rn>中保存着内存的地址,

?? ?{!}加上了感叹号,指令执行后,rn的值会更新,等于下一个内存单元地址。

?? ?< register list>表示寄存器列表,指令中寄存器列表和内存单元对应关系为:编号低得寄存器对应内存中得低地址单元,
?? ??? ?
?? ??? ??? ??? ??? ?编号高的寄存器对应内存中的高地址单元。

?? ?{^}有两个含义:如果< register list>中有pc寄存器,它表示指令执行之后,spsr寄存器的值将自动复制到cpsr寄存器中–这常用于从中断处理函数中返回;

?? ??? ??? ??? ??? 如果< register list>中没有pc寄存器,{^}表示操作的是用户模式下的寄存器,而不是当前特权模式的寄存器。
?? ?
?? ?例子示范

?? ??? ?stmia sp!, {r6, lr}?? ??? ??? ?// 以sp为基地址,把后面寄存器的值依次存入sp的顺序地址
?? ??? ?ldmdb sp!, {r6, pc}?? ??? ??? ?// 以sp为基地址,取sp的顺序地址的值放入到后面的寄存器


?? ??? ?//中断返回,"^"表示将spsr的值复制到cpsr
?? ??? ?//于是从irq模式返回被中断的工作模式
?? ??? ?//"!"使得指令执行后,sp=sp+14*4

?? ?! : 当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变.
?? ?^ : 当指令为LDM且寄存器列表中包含R15,选用该后缀时表示除了正常的数据传送之外,还将SPSR复制到CPSR.
?? ??? ?同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器.


?? ?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,因为异常返回后需要恢复异常发生前的工作状态

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:46:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:52:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码