ARM汇编编程基础之六-其它寻址模式与其它指令
我们在“基本寻址模式与基本指令”一文中学习了最常用的3种寻址方式。下面介绍其它寻址方式。
1、基址寻址
基址寻址就是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能部件寄存器访问等。基址寻址指令举例如下:
LDR R1,[R2,#0x0C]
R2的值+0x0C形成内存地址,读取内存中该地址上的内容,放入R1
其它额外需要了解的内容:
§零偏移。 如:LDR R0,[R1]
§前索引偏移。 如:LDR R0,[R1,#0x04]!,表示将R1的值加上4后作为内存地址,并且指令执行结束时,R1本身的值也要加4。这里!表示要回写
§程序相对偏移。 如:LDR R0,labe1,表示将标号label所代表的地址处存放的内容放入R0,相当于LDR R0, [PC, #某个常数]
§后索引偏移。 如:LDR R0,[R1],#0x04,表示将R1的值作为内存地址,并且指令执行结束时,R1本身的值要加4
2、多寄存器寻址
多寄存器寻址一次可传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器。多寄存器寻址指令举例如下:
LDMIA R1!,{R2-R4,R6} ,它是ldr的多寄存版本,将内存中的4个字放入寄存器R2,R3,R4,R6中
两点说明:
1)、R1!中的!号表示在指令执行完成后,要改变(回写)基址寄存器(R1)的值
2)、寄存器列表{R2-R4, R6}中的顺序并不要紧。最终寄存器与内存地址的对应关系是:编号小的寄存器与内存的低地址相对应
两点问题:
1)、为什么内存起地址是0x40000000,而不是0x40000004
2)、为什么内存地址是从0x40000000 ---- 0x4000000C,而不是从0x3FFFFFF4 ----
要解释上面2个问题,其实也很简单。其实多寄存加载指令ldm总共有4个:ldmia、 ldmib、 ldmda、 ldmdb。ia的意思是increase after,ib的意思是increase before,da的意思是decrease after,db的意思是decrease before。以LDMIA R1!, {R2-R4, R6}为例子,这里的ia是指办事(将内存中的数加载到寄存器)之后增加基址寄存器(R1)的值。这条指令的执行过程从逻辑上看,如下:
1)、先办事:将R1的值(0x40000000)作为内存地址,到该地址处取得数(0x01),加载到寄存器R2中
2)、后增加:将R1的值从0x40000000增加为0x40000004
再重复上面的操作3次,分别将内存中的数0x02、0x03、0x04放到寄存器中R3、R4、R6中,最后R1的值变为0x40000010。
这个例子中,如果将ldmia改为ldmib,则R2、R3、R4、R6中存放的是0x02、0x03、0x04、内存0x40000010处的内容,最后R1的值为0x40000010。
除了4条多寄存器加载指令外,还有4条类似的多寄存器存储指令,分别是stria、 strib、 strda、 strdb
3、堆栈寻址
由于ARM指令集没有专门的出栈和入栈指令,所以ARM汇编程序是采用SP作为栈指针,以stm指令完成入栈操作,以ldm指令完成出栈操作。
以入栈后SP的值是增加还是减少为依据,可将堆栈类型划分为递增堆栈(向上生长)和递减堆栈(向下生长);
以SP所指向的内存处存放的是栈顶元素还是下一次要入栈的元素,可将堆栈类型划分为满堆栈和空堆栈
那么当堆栈类型为空递减堆栈时候,入栈操作应该使用什么指令?出栈操作应该使用什么指令?进一步,如果堆栈类型为空递增、满递增、满递减堆栈,又将如何呢?如果你不看下面的答案,我相信你一定会让这几个问题折磨得做很多的脑力体操,然后感叹ARM指令集的设计者太不为你这样的程序员考虑了,给了你本不应该由你承担的负荷。但事实上正相反,ARM指令集的设计者充分理解了你作为程序员的苦恼,请看下面的答案。
数据块传送 | 堆栈操作 | 说明 |
存储 | 压栈 | |
STMDA | STMED | 空递减 |
STMIA | STMEA | 空递增 |
STMDB | STMFD | 满递减 |
STMIB | STMFA | 满递增 |
数据块传送 | 堆栈操作 | 说明 |
加载 | 出栈 | |
LDMDA | LDMFA | 满递增 |
LDMIA | LDMFD | 满递减 |
LDMDB | LDMEA | 空递增 |
LDMIB | LDMED | 空递减 |
这2张表的第一、三列回答了前面你绞尽脑汁回答的问题。而第二列则体现了ARM指令集的设计者对作为程序员的你的充分体贴。第二列中的ED、EA、FD、FA分别表示empty descend(空递减)、 empty ascend(空递增)、 full descend(满递减)、 full ascend(满递增),其含义是说,如果你采用的是空递减(空递增、满递减、满递增)堆栈的话,入栈操作则使用指令STMED(STMEA、STMFD、STMFA),出栈操作则使用指令LDMED(LDMEA、LDMFD、LDMFA)。从此你
ARM汇编编程寻址模 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)