欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

ARM 汇编基础速成5:连续存取

来源:本站整理 作者:佚名 时间:2017-07-13 TAG: 我要投稿
接下来我们把R1和R2指向array_buff[0]以及array_buff[2]。在获取了这些指针后,我们就可以操作这个数组了。
ldr r1, array_buff_bridge    /* array_buff[0]的地址 -> r1 */
ldr r2, array_buff_bridge+4  /* array_buff[2]的地址 -> r2 */
执行完上面这两条指令后,R1和R2的变化。
gef> info register r1 r2
r1      0x100d0     65744
r2      0x100d8     65752
下一条LDM指令从R0指向的内存中加载了两个字的数据。因为R0指向words[3]的起始处,所以words[3]的值赋给R4,words[4]的值赋给R5。

ldm r0, {r4,r5}              /* words[3] -> r4 = 0x03; words[4] -> r5 = 0x04 */
所以我们用一条指令加载了两个数据块,并且放到了R4和R5中。
gef> info registers r4 r5
r4      0x3      3
r5      0x4      4
看上去不错,再来看看STM指令。STM指令将R4与R5中的值0x3和0x4存储到R1指向的内存中。这里R1指向的是array_buff[0],也就是说 array_buff[0] = 0x00000003以及array_buff[1] = 0x00000004。如不特定指定,LDM与STM指令操作的最小单位都是一个字(四字节)。

stm r1, {r4,r5}              /* r4 -> array_buff[0] = 0x03; r5 -> array_buff[1] = 0x04 */
值0x3与0x4被存储到了R1指向的地方0x100D0以及0x100D4。
gef> x/2w 0x000100D0
0x100d0 :  0x00000003   0x00000004
之前说过LDM和STM有多种形式。不同形式的扩展字符和含义都不同:
IA(increase after)
IB(increase before)
DA(decrease after)
DB(decrease before)
这些扩展划分的主要依据是,作为源地址或者目的地址的指针是在访问内存前增减,还是访问内存后增减。以及,LDM与LDMIA功能相同,都是在加载操作完成后访问对地址增加的。通过这种方式,我们可以序列化的向前或者向后从一个指针指向的内存加载数据到寄存器,或者存放数据到内存。如下示意代码 。
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 */
在执行完这两条代码后,R4到R6寄存器所访问的内存地址以及存取的值是0x000100D0,0x000100D4,以及0x000100D8,值对应是 0x3,0x4,以及0x5。
gef> info registers r4 r5 r6
r4     0x3     3
r5     0x4     4
r6     0x5     5
gef> x/3w 0x000100D0
0x100d0 : 0x00000003  0x00000004  0x00000005
而LDMIB指令会首先对指向的地址先加4,然后再加载数据到寄存器中。所以第一次加载的时候也会对指针加4,所以存入寄存器的是0X4(words[4])而不是0x3(words[3])。
dmib 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 */
执行后的调试示意:
gef> x/3w 0x100D4
0x100d4 : 0x00000004  0x00000005  0x00000006
gef> info register r4 r5 r6
r4     0x4    4
r5     0x5    5
r6     0x6    6
当用LDMDA指令时,执行的就是反向操作了。R0指向words[3],当加载数据时数据的加载方向变成加载words[3],words[2],words[1]的值到R6,R5,R4中。这种加载流程发生的原因是我们LDM指令的后缀是DA,也就是在加载操作完成后,会将指针做递减的操作。注意在做减法模式下的寄存器的操作是反向的,这么设定的原因为了保持让编号大的寄存器访问高地址的内存的原则。
多次加载,后置减法:

ldmda r0, {r4-r6} /* words[3] -> r6 = 0x03; words[2] -> r5 = 0x02; words[1] -> r4 = 0x01 */
执行之后,R4-R6的值:
gef> info register r4 r5 r6
r4     0x1    1
r5     0x2    2
r6     0x3    3
多次加载,前置减法:

ldmdb r0, {r4-r6} /* words[2] -> r6 = 0x02; words[1] -> r5 = 0x01; words[0] -> r4 = 0x00 */
执行之后,R4-R6的值:
gef> info register r4 r5 r6
r4 0x0 0
r5 0x1 1
r6 0x2 2
多次存储,后置减法:
stmda r2, {r4-r6} /* r6 -> array_buff[2] = 0x02; r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00 */
执行之后,array_buff[2],array_buff[1],以及array_buff[0]的值:
gef> x/3w 0x100D0
0x100d0 : 0x00000000 0x00000001 0x00000002
多次存储,前置减法:

stmdb r2, {r4-r5} /* r5 -> array_buff[1] = 0x01; r4 -> array_buff[0] = 0x00; */
执行之后,array_buff[1],以及array_buff[0]的值:
gef> x/2w 0x100D0
0x100d0 : 0x00000000 0x00000001
PUSH和POP
在内存中存在一块进程相关的区域叫做栈。栈指针寄存器SP在正常情形下指向这篇区域。应用经常通过栈做临时的数据存储。X86使用PUSH和POP来访问存取栈上数据。在ARM中我们也可以用这两条指令:

上一页  [1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载