现在的位置: 首页 > 综合 > 正文

理解LDM和STM多寄存器寻址 堆栈指针sp例子

2013年09月23日 ⁄ 综合 ⁄ 共 2557字 ⁄ 字号 评论关闭

 堆栈寻址的命令LDMFA/STMFALDMEA/STMEALDMFD/STMFDLDMED/STMED

      LDMSTM表示多寄存器寻址,即一次可以传送多个寄存器值。

      LDM:一次装载多个,这里用来出栈。(另有,LDR寄存器间接寻址 也是装载r2内容作指针指向的内存到R1,如:LDRR1,[R2] 

      STM:一次存储多个,这里用来入栈。(另有,STR寄存器间接寻址 也是把R1写入到r2内容作指针指向的内存,如:LDRR1,[R2] 

      F/E表示指针指向的位置

      Ffull满堆栈,表示堆栈指针指向最后一个入栈的有效数据项。

      Eempty空堆栈,表示堆栈指针指向下一个要放入的空地址。

      A/D表示堆栈的生长方式

      A:堆栈向高地址生长,即递增堆栈。

      D:堆栈向低地址生长,即递减堆栈。

      注意:有一个约定,编号低的寄存器在存储数据或者加载数据时对应于存储器的低地址。

            FDEDFAEA指定是满栈还是空栈,是升序栈还是降序栈,用于堆栈寻址。

                一个满栈的栈指针指向上次写的最后一个数据单元

                空栈的栈指针指向第一个空闲单元。

                一个降序栈是在内存中反向增长而升序栈在内存中正向增长。

            {!}:若选用了此后缀,则当指令执行完毕后,将最后的地址写入基址寄存器。 

            {^}:当regs中不包含PC时,该后缀用于指示指令所用的寄存器为用户模式下的寄存器,

                 否则指示指令执行时,将寄存器SPSR的值复制到CPSR中。

 

例:

AREA Example,CODE,READONLY
 ENTRY     
 EXPORT Start
 EXPORT loop
 EXPORT OVER                   
Start       
 
 mov r4,#4
 mov r5,#5
 mov r6,#6
 add r0,sp,#0
 stmfa sp!,{r4,r5,r6}   ; 1:stmfa,2: stmfd,3: stmea,4: stmed
 
 add r1,sp,#0
 
 b loop
loop
 b loop     
          
OVER    
 END  

 

内存中的表示:

假设sp指向0x00000000地址

1: stmfa sp!,{r4,r5,r6} 

                          0    1  2   3       4    5    6    7      8   9    a   b     c   d    e    f

0x0000 0000  10 00 FF E7   04 00 00 00     05 00 00 00   06 00 00 00

              f: sp 的下一上地址

             a:向高地址+1

             sp:0x0000 000C

 

2: stmfd sp!,{r4,r5,r6} 

                          0    1  2   3       4    5    6    7      8   9    a   b     c   d    e    f

0xFFFF FFF0  10 00 FF E7   04 00 00 00     05 00 00 00    06 00 00 00

              f: sp 的下一上地址

             d:向低地址+1

             sp:0xFFFF FFF4

 

3: stmea sp!,{r4,r5,r6} 

                          0    1  2   3       4    5    6    7      8   9    a   b     c    d    e    f

0x0000 0000  04 00 00 00     05 00 00 00    06 00 00 00  00  E8 00 E8

              f: sp 的下一上地址

             a:向高地址+1

             sp:0x0000 000C

 

4:  stmed sp!,{r4,r5,r6} 

                          0    1  2   3       4    5    6    7      8   9    a   b      c   d    e    f

0xFFFF FFF0  10 00 FF E7   00  E8 00 E8  
04 00 00 00     05 00 00 00    

0x0000 0000   06 00 00 00  00  E8 00 E8   10 00 FF E7    00  E8 00 E8  

              f: sp 的下一上地址

             d:向低地址+1

             sp:0xFFFF FFF4

 

 

 

 又如:

stmed sp!,{r4,r5,r6}
 mov r2,#2
 stmed sp!,{r2}

 

                          0    1  2   3       4    5    6    7      8   9    a   b      c   d    e    f

0xFFFF FFF0  10 00 FF E7  
02  00 00 00  
04 00 00 00     05 00 00 00    

0x0000 0000   06 00 00 00  00  E8 00 E8   10 00 FF E7    00  E8 00 E8  

              f: sp 的下一上地址

             d:向低地址+1

             sp:0xFFFF FFF0

 ldmed sp!,{r7,r8}

             r7:0x02    (正确)

            r8:0x04   (正确)

 ldmfd sp!,{r7,r8}

             r7:0xe7ff0001  (不是想要的结果。)

            r8:0x02  (不是想要的结果。)

所以,压入堆栈,用的ed参数。弹出堆栈也要用回ed ,不能用fd.更不能用fa.访问到的内存是不是想要的。

抱歉!评论已关闭.