Chinaunix首页 | 论坛 | 博客
  • 博客访问: 343682
  • 博文数量: 96
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 152
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-02 09:27
文章分类

全部博文(96)

文章存档

2017年(2)

2016年(30)

2015年(38)

2014年(25)

2013年(1)

我的朋友

分类: 嵌入式

2016-08-15 11:53:49

原文地址:ldm和stm用法详解 作者:枫露清愁

数据块传输指令用于加载(LDM)或者存储(STM)当前有效寄存器的任意子集。
它们支持所有可能的堆栈模式,维持空或者满的堆栈,此堆栈可以向上或者向下,在保存或者恢复内容,
移动主存储器的大数据块是非常有效的。


当LDM/STM没有被用于堆栈,而只是简单地表示地址前向增加,后向增加,前向减少,后向减少时,由IA,IB,DA,DB控制。
        IA    ---->    Increment    After    每次传送后地址加4
        IB    ---->    Increment    Before    每次传送前地址加4
        DA    ---->    Decrement    After    每次传送后地址减4
        DB    ---->    Decrement    Before    每次传送前地址减4


堆栈请求格式,FD,ED,FA,EA定义了前/后向索引和上/下位,F,E表示堆栈满或者空。
    A 和D 定义堆栈是递增还是递减,如果递增,STM将向上,LDM向下,如果递减,则相反。
        FA    ---->    Full    Ascending        满递增堆栈           
        FD    ---->    Full    Descending        满递减堆栈 
        EA    ---->    Empty    Ascending    空递增堆栈
        ED    ---->    Empty    Descending    空递减堆栈


操作方式是:STM(IA/FD等) 基址寄存器 寄存器组


ARM 微处理器支持这四种类型的堆栈工作方式

1.Full descending 满递减堆栈——FD 堆栈首部是高地址,堆栈向低地址增长。栈指针总是指向堆栈最后一个元素(最后
一个元素是最后压入的数据)。ARM-Thumb过程调用标准和ARM、Thumb C/C++ 编译器总是使用Full descending 类型堆栈。

2.Full ascending 满递增堆栈——FA 堆栈首部是低地址,堆栈向高地址增长。栈指针总是指向堆栈最后一个元素(最后
一个元素是最后压入的数据)。

3.Empty descending 空递减堆栈——ED 堆栈首部是高地址,堆栈向低地址增长。栈指针总是指向下一个将要放入数据的空位置。

4.Empty ascending 空递增堆栈——EA 堆栈首部是低地址,堆栈向高地址增长。栈指针总是指向下一个将要放入数据的空位置。


其中LDMIA和STMDB成对使用,因为堆栈的时候是先减后存,出栈的时候就应该是取后加;同理可推出其他


对于堆栈方式,LDMFD和STMFD是成对使用,因为堆栈方式和出栈方式要是相同的。阅读过下面的分析就能理解了


具体对应的存取方式可参见下表:




下面以几条指令来说明一下存取时寄存器和内存地址的对应关系:

STMIA r0!,{r1,R3,R5}
数据块传送,先存后增,产生的结果是:
r1存至r0
R3存至r0+4
R5存至r0+8
r0最后指向的地址是r0(初)+12


因为是先存后增,所以寄存器组存数据也是递增的,从r1递增取至R5


成对使用的取数据操作是:
LDMDB r0!,{r1,R3,R5} 
这个时候r0指向的地址已经是r0(初)+12,先减后取,所以产生的结果是:
r0+8取至R5
r0+4取至R3
r0取至r1


因为是先减后取,所以从寄存器组取数据也是递减的,从R5递减取至r1


所以无论是递减存取还是递增存取,寄存器组里的高位寄存器对应到高地址,低位寄存器对应到低地址。


对于堆栈指令,首先根据STM判断地址增加方向,如:
STMFA r0!,{r1,R3,R5}
满递增堆栈,先加后存(可认为满是指当前寄存器指向的地址已经有数据,不可存了,要先改变地址),操作结果是:
r1存至r0+4
R3存至r0+8
R5存至r0+12


根据STM判断方向是向高地址递增的,那么LDMFA的方向刚好是相反
LDMFA r0!,{r1,R3,R5}
满递增出栈,先取后减(可认为满是代表当前寄存器指向的地址有数据,可直接取),结果是:
r0+12取至R5
r0+8取至R3
r0+4取至r1


下面是每条指令存取的图解:

(1)IA
STMIA r0!,{r1,R2, R3,r14}
先传后增,寄存器→RAM
效果图:


LDMIA r0!,{r1,R2, R3,r14}
先传后增, RAM →寄存器
效果图:


(2)IB
STMIB r0!,{r1,R2, R3,r14}
先增后传,寄存器→RAM
效果图:


LDMIB r0!,{r1,R2, R3,r14}
先增后传, RAM →寄存器
效果图:


(3)DA
STMDA r0!,{r1,R2, R3,r14}
先传后减, 寄存器→ RAM
效果图:


LDMDA r0!,{r1,R2, R3,r14}
先传后减, RAM → 寄存器
效果图:


(4)DB
STMDB r0!,{r1,R2, R3,r14}
先减后传,寄存器→ RAM
效果图:


LDMDB r0!,{r1,R2, R3,r14}
先减后传, RAM → 寄存器
效果图:


(5)FA
STMFA SP!,{r0,r1,R2,r14}
满递增入栈,r13为基址地址
效果图:


LDMFA SP!,{r0,r1,R2,r14}
满递增出栈,r13为基址地址
效果图:


(6)FD
STMFD SP!,{r0,r1,R2,r14}
满递减入栈,r13为基址地址
效果图:


LDMFD SP!,{r0,r1,R2,r14}
满递减出栈,r13为基址地址
效果图:


(7)EA
STMEA SP!,{r0,r1,R2,r14}
空递增入栈,r13为基址地址
效果图:


LDMEA SP!,{r0,r1,R2,r14}
空递增出栈,r13为基址地址
效果图:


(8)ED
STMED SP!,{r0,r1,R2,r14}
空递减入栈,r13为基址地址
效果图:


LDMED SP!,{r0,r1,R2,r14}
空递减出栈,r13为基址地址
效果图:




参考资料:http://blog.chinaunix.net/uid-28458801-id-3791987.html


阅读(2240) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~