2015年(1)
分类: 嵌入式
2015-03-20 13:40:53
原文地址:arm ldm stm指令解析 作者:gududesiling
转自:http://hi.baidu.com/zp2000/blog/item/26cacf112016a711b8127b6e.html,由于原始帖子已经被删了,所以我转成原创并进行修改了,如下: 下面讲述之前,说明一下:(博客中还有一篇文章,里面涉及所有的arm指令的讲解,如果想要看到涉及下面4个指令更多的例程,请看另篇,链接为:http://blog.chinaunix.net/uid-25100840-id-340479.html) 这里比较下容易混淆的四条指令,已经在这4条指令的混淆上花费了很多精力,现在做个小结,LDR,STR,LDM,STM这四条指令,关于LDM和STM的说明,见另外一个说明文件,说明了这两个文件用于栈操作时的注意事项。 (1)LDR:L表示LOAD,LOAD的含义应该理解为:Load from memory into register。下面这条语句就说明的很清楚: LDR R1, [R2] R1<——[R2] 就是把R2所指向的存储单元的内容的值(一个memory地址内的值),读取到R1中(一个register)
(2)STR:S表示STORE,STORE的含义应该理解为:Store from a register into memory。下面这条语句表示的很清楚: STR R1, [R2] R1——>[R2] 就是把寄存器R1中的内容“保存”到R2所指向的存储的单元中(一个memory地址)。 显然,这两条语句都有个特点,就是寄存器写在前面(左边)而内存地址写在后面(右边),数据传送的方向则是恰好相反的。 下面对LDM和STM介绍,使用sp来介绍,因为实际使用中,和sp一起使用更多。
(3)LDM:L的含义仍然是LOAD,即是Load from memory into register。 虽然貌似是LDR的升级,但是,千万要注意,这个指令运行的方向和LDR是不一样的,是从左到右运行的。该指令是将内存中堆栈内的数据,批量的赋值给寄存器,即是出栈操作;其中堆栈指针一般对应于SP,注意SP是寄存器R13,实际用到的却是R13中的内存地址,只是该指令没有写为[R13],同时,LDM指令中寄存器和内存地址的位置相对于前面两条指令改变了,下面的例子: LDMFD SP! , {R0, R1, R2} 实际上可以理解为: LDMFD [SP]!, {R0, R1, R2} 意思为:把sp指向的3个连续地址段(应该是3*4=12字节(因为为r0,r1,r2都是32位))中的数据拷贝到r0,r1,r2这3个寄存器中去(如果这个地方还不懂的话,可以参看我文章开头提到的链接,里面有详细的图解)
(4)STM:S的含义仍然是STORE,与LDM是配对使用的,其指令格式上也相似,即区别于STR,是将堆栈指针写在左边,而把寄存器组写在右边。 STMFD SP!, {R0} 同样的,该指令也可理解为: STMFD [SP]!, {R0} 意思是:把R0保存到堆栈(sp指向的地址)中。 显然,这两个堆栈操作指令也有个特点,就是寄存器组写在后面(右边)而堆栈指针写在前面(左边),而且实际上使用的是堆栈指针中的内存地址,这一点与前面两条指令是有区别的。 (补充:sp后面的!,作用是指命令执行完后,对应的地址值赋给sp,对于例程的SDM,是说最后sp的值应该是sp+3*4=sp+12) 这四条指令中,前面两条和后面两条其实联系不多,反而是差别很大,因此,可以直接把这两组指令区分开来,认为它们之间没有联系,这样避免误解。 大家如果还有什么不清楚的地方可以问我,或者觉得我说的有错也可以问 |