LOAD/STORE MULTIPLE(数据加载/存储多个寄存器)

https://azeria-labs.com/load-and-store-multiple-part-5/

.data

array_buff:
 .word 0x00000000             /* array_buff[0] */
 .word 0x00000000             /* array_buff[1] */
 .word 0x00000000             /* array_buff[2]. This element has a relative address of array_buff+8 */
 .word 0x00000000             /* array_buff[3] */
 .word 0x00000000             /* array_buff[4] */

.text
.global _start

_start:
 adr r0, words+12             /* address of words[3] -> r0 */
 ldr r1, array_buff_bridge    /* address of array_buff[0] -> r1 */
 ldr r2, array_buff_bridge+4  /* address of array_buff[2] -> r2 */
 ldm r0, {r4,r5}              /* words[3] -> r4 = 0x03; words[4] -> r5 = 0x04 */
 stm r1, {r4,r5}              /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04 */
 ldmia r0, {r4-r6}            /* words[3] -> r4 = 0x03, words[4] -> r5 = 0x04; words[5] -> r6 = 0x05; */
 stmia r1, {r4-r6}            /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04; r6 -> array_buff[2] = 0x05 */
 ldmib r0, {r4-r6}            /* words[4] -> r4 = 0x04; words[5] -> r5 = 0x05; words[6] -> r6 = 0x06 */
 stmib r1, {r4-r6}            /* r4 -> array_buff[1] = 0x04; r5 -> array_buff[2] = 0x05; r6 -> array_buff[3] = 0x06 */
 ldmda r0, {r4-r6}            /* words[3] -> r6 = 0x03; words[2] -> r5 = 0x02; words[1] -> r4 = 0x01 */
 ldmdb r0, {r4-r6}            /* words[2] -> r6 = 0x02; words[1] -> r5 = 0x01; words[0] -> r4 = 0x00 */
 stmda r2, {r4-r6}            /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */
 stmdb r2, {r4-r5}            /* r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00; */
 bx lr

words:
 .word 0x00000000             /* words[0] */
 .word 0x00000001             /* words[1] */
 .word 0x00000002             /* words[2] */
 .word 0x00000003             /* words[3] */
 .word 0x00000004             /* words[4] */
 .word 0x00000005             /* words[5] */
 .word 0x00000006             /* words[6] */

array_buff_bridge:
 .word array_buff             /* address of array_buff, or in other words - array_buff[0] */
 .word array_buff+8           /* address of array_buff[2] */

开始调试上面的代码gdb ldr

下断点

break _start

运行

run          //运行到断点处

x/i $pc:查看接下来反汇编指令(60是10进制数,转成16进制为3c)

 0x10074 <_start>:  add r0, pc, #60 ; 0x3c

使用i r pc查询到 的pc当前存储的值为0x10074

pc             0x10074  0x10074 <_start>

也就是说下一条指令是用0x100b0=(0x10074+0x3c),赋值给r0,但是实际并不是,执行下面的单步执行 ,执行完第一条指令,使用i r r0发现结果为0x100b8

r0             0x100b8  65720
为什么结果会比计算的值多8呢?

参考:什么时候PC+8,PC+4,PC-4,PC-8
[图片上传失败...(image-cefda3-1543372618746)]
需要知道的点:
1、每条指令执行有三个流程:取指、译码、执行
2、当第一条汇编指令取指完成后,紧接着就是第二条指令的取指,然后第三条...如此嵌套
3、取指完成后,PC就指向了第二条指令,此时PC=PC+4
所以可以知道:第一条指令执行的时候,也是第三条指令的取指的时候,即PC=PC+8

单步执行

nexti/ni        //步入
stepi/si        //步过

adr r0, words+12:将words+12处的内存地址获取并存到r0。
words+12->0x00000003(这个地址存储的值),

i r r0        //获取r0寄存器数据:0x100b8
x/3w 0x100b8        //十六进制,字类型查看0x100b8和其之后的两个地址的数据
结果:0x100b8 <words+12>:  3   4   5

ldm r0, {r4, r5}

ldm 源,目的寄存器:r0的值为内存地址,其指向的值附给r4,r0+4指向的值给r5

r0: 寄存其中的值
r0             0x100b8  0x100b8

内存地址指向的值
x/w    0x100b8      >>    3
x/w    0x100bc      >>    4

stm r1, {r4, r5}

stm 目的地址,{源寄存器}:将寄存器中的值,放入目的地址指向的位置处
执行前:

$r1  : 0x000200d0
$r4  : 0x3       
$r5  : 0x4 
x/2w 0x100d0   (0x000100d0指向的值>>0x0; 0x000100d4>>0x0)

执行后si

x/2w 0x200d0
结果为:0x200d0:    0x3 0x4

ldmia、stmia

-IA(之后递增)ldmldmia是相同的,每次加载下一条指令,源地址都会增加4字节(一个字的值),stmia也一样

ldmia r0, {r4-r6} /* r0 -> r4 = 0x03, r0+4 -> r5 = 0x04; r0+8 -> r6 = 0x05; */ 
stmia r1, {r4-r6} /* r4 -> r1 = 0x03; r5 -> r1+4 = 0x04; r6 -> r1+8 = 0x05 */

ldmib、stmib

-IB(之前递增):在加载下一条指令之前增加4字节(一个字的值)

ldmia r0, {r4-r6} /* r0 -> r0+4 = 0x03, r0+8 -> r5 = 0x04; r0+12 -> r6 = 0x05; */ 
stmia r1, {r4-r6} /* r4 -> r1+4 = 0x03; r5 -> r1+8 = 0x04; r6 -> r1+12 = 0x05 */

LDMDA、STMDA:递减情况下,目的寄存器是先赋值给后面,同样从源寄存器中取指时也是先从后面取值

-DA(之后递减)

ldmda r0, {r4-r6} /* r0 -> r6 = 0x03; r0-4 -> r5 = 0x02; r0-8 -> r4 = 0x01 */
stmda r2, {r4-r6} /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */

LDMDB、STMDB

-DB(之前递减)

ldmdb r0, {r4-r6} /* r0-4 -> r6 = 0x02; r0-8 -> r5 = 0x01; r0-12 -> r4 = 0x00 */
stmdb r2, {r4-r5} /* r5 -> r2-4 = 0x01; r4 -> r2-8 = 0x00; */

PUSH AND POP

知识点
PUSH:

  1. SP-4
  2. 数据存储到SP指向的新地址处

POP

  1. SP的值先存储到某个寄存器中
  2. SP+4

实例

.text
.global _start

_start:
   mov r0, #3
   mov r1, #4
   push {r0, r1}
   pop {r2, r3}
   stmdb sp!, {r0, r1}
   ldmia sp!, {r4, r5}
   bkpt

汇编后:

      0x10054 <_start+0>       mov    r0,  #3
      0x10058 <_start+4>       mov    r1,  #4
->   0x1005c <_start+8>       push   {r0,  r1}
      0x10060 <_start+12>      pop    {r2,  r3}
      0x10064 <_start+16>      push   {r0,  r1}
      0x10068 <_start+20>      pop    {r4,  r5}
      0x1006c <_start+24>      bkpt   0x0000
  • push:先从后面压入堆栈
 0x1005c <_start+8>       push   {r0,  r1}    //r0=3;r1=4

堆栈信息:
0xbefff2a8|+0x0000: 0x00000003  <-$sp
0xbefff2ac|+0x0004: 0x00000004
  • pop:先赋值给前面的寄存器
 0x10060 <_start+12>      pop    {r2,  r3}

寄存器信息
$r2  : 0x3       
$r3  : 0x4 
  • stmdb sp!就是push
  • ldmia sp!就是pop
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值