当前位置:网站首页>ARM V7 连续加载/存储
ARM V7 连续加载/存储
2022-06-25 12:02:00 【xiaozhiwise】
/*
* 2018/12/18 10:15 qing
*/
/*
* 连续加载/存储
*/
使用LDM(load multiple)以及STM(store multiple)
stmdb r0!, {r4-r11, r14} /* 将寄存器R4~R11也保存到堆栈r0中 [[ 从寄存器到内存 ]] */
ldmia r0!, {r4-r11, r14} /* 从堆栈r0恢复到R4~R11,R14 [ [从内存到寄存器 ]] */
.data
array_buff:
.word 0x00000000 /* array_buff[0] */
.word 0x00000000 /* array_buff[1] */
.word 0x00000000 /* array_buff[2] 这一项存的是指向array_buff+8的指针 */
.word 0x00000000 /* array_buff[3] */
.word 0x00000000 /* array_buff[4] */
.text
.global main
main:
adr r0, words + 12 /* wrods[3] 的地址 ---> r0 */
ldr r1, array_buff_bridge /* array_buff[0]的地址 -> r1 */
ldr r2, array_buff_bridge + 4 /* 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] = 0x4; r6 --> array_buff[2] = 0x5 */
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-r6} /* 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 /* array_buff[0] address */
.word array_buff + 8 /* array_buff[2] address */
.word标识是对内存中长度为32位的数据块作引用。这对于理解代码中的偏移量很重要。
所以程序中由.data段组成的数据,内存中会申请一个长度为5的4字节数组array_buff。我们的所有内存存储操作,都是针对这段内存中的数据段做读写的。
而.text端包含着我们对内存操作的代码以及只读的两个标签,
一个标签是含有七个元素的数组,另一个是为了链接.text段和.data段所存在的对于array_buff的引用。
/*
* 下面就开始一行行的分析
*/
adr r0, words+12 /* words[3]的地址 -> r0 */
用ADR指令来获得words[3]的地址,并存到R0中。我们选了一个中间的位置是因为一会要做向前以及向后的操作。
gef> break _start
gef> run
gef> nexti
R0当前就存着words[3]的地址了,也就是0x80B8。也就是说,我们的数组word[0]的地址是:0x80AC(0x80B8-0XC)。
gef> x/7w 0x00080AC
0x80ac <words>: 0x00000000 0x00000001 0x00000002 0x00000003 /* 0x80ac 80B0 80B4 80B8 */
0x80bc <words+16>: 0x00000004 0x00000005 0x00000006 /* 0x80bc 80C0 80C4 */
接下来我们把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 /* 0x100d0 = 65744 */
r2 0x100d8 65752 /* 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指令将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 <array_buff>: 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 <array_buff>: 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 <array_buff+4>: 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 <array_buff>: 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 <array_buff>: 0x00000000 0x00000001
边栏推荐
- Thingpanel publie le client mobile IOT (Multi - images)
- R语言使用构建有序多分类逻辑回归模型、epiDisplay包的ordinal.or.display函数获取有序logistic回归模型的汇总统计信息(变量对应的优势比及其置信区间、以及假设检验的p值)
- 19、wpf之事件转命令实现MVVM架构
- SMS verification before deleting JSP
- How far is it from the DBF of VFP to the web salary query system?
- Share 7 immortal wallpaper websites, let the new wallpaper give you a little joy, and don't fall into the repetition year after year.
- Simple use of stream (II)
- Quarkus SaaS dynamic data source switching implementation, simple and perfect
- Dark horse shopping mall ---3 Commodity management
- JSON format processing
猜你喜欢
Dark horse shopping mall ---2 Distributed file storage fastdfs
15、wpf之button样式小记
ROS notes (06) - definition and use of topic messages
Dark horse shopping mall ---3 Commodity management
How do super rookies get started with data analysis?
How to use ARIMA model for prediction?
VFP serial port communication is difficult for 9527. Maomao just showed his skill and was defeated by kiss
How to use SPSS to do grey correlation analysis? Quick grasp of hand-to-hand Teaching
Startups must survive
Actual combat summary of Youpin e-commerce 3.0 micro Service Mall project
随机推荐
Two ways of redis persistence -- detailed explanation of RDB and AOF
云原生数据湖以存储、计算、数据管理等能力通过信通院评测认证
Real software developers will use this method to predict the future
VFP uses Kodak controls to control the scanner to solve the problem that the volume of exported files is too large
What should I do to dynamically add a column and button to the gird of VFP?
Detailed explanation of Flink checkpoint specific operation process and summary of error reporting and debugging methods
Dark horse shopping mall ---3 Commodity management
一款好用的印章设计工具 --(可转为ofd文件)
如果你也想做自媒体,不妨听大周给您点建议
Deeply understand Flink SQL execution process based on flink1.12
Flink partition policy
黑马畅购商城---2.分布式文件存储FastDFS
Thingspanel releases Internet of things mobile client (multiple pictures)
为什么ping不通网站 但是却可以访问该网站?
VFP develops a official account to receive coupons, and users will jump to various target pages after registration, and a set of standard processes will be sent to you
一個硬件工程師走過的彎路
学习笔记 2022 综述 | 自动图机器学习,阐述 AGML 方法、库与方向
Gradle知识点
黑马畅购商城---1.项目介绍-环境搭建
设置图片的透明度从左到右渐变