【愚公系列】2022年06月 ARM汇编 LDM和STM

举报
愚公搬代码 发表于 2022/06/30 20:52:22 2022/06/30
【摘要】 LDM(载入多个值)和STM(存储多个值).dataarray_buff:.word 0x00000000 /* array_buff[0] */.word 0x00000000 /* array_buff[1] */.word 0x00000000 /* array_buff[2]. This element has...

LDM(载入多个值)和STM(存储多个值)

.data

array_buff:

.word 0x00000000 /* array_buff[0] */

.word 0x00000000 /* array_buff[1] */

.word 0x00000000 /* array_buff[2]. This element hasa 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 /
(我们使用ADR指令(偷懒的办法)将数组第四部分(word[3])的地址传送给R0。我们用R0指向word数组的中间位置,所以我们可以从这开始向前或者向后移动指针)
ldr r1, array_buff_bridge /
address of array_buff[0] -> r1 */

ldr r2, array_buff_bridge+4 /* address of array_buff[2] -> r2 /
(执行完上面的两条命令后,R1,R2中分别包含了 array_buff[0]的地址和 array_buff[2]的地址)
ldm r0, {r4,r5} /
words[3] -> r4 = 0x03;words[4] -> r5 = 0x04 /
(使用LDM指令,将R0指向的内存中,取两个字的数据出来。由于之前我们让R0指向了word[3],因此word[3]的值会被存入R4, word[4]的会被存入R5)
stm r1, {r4,r5} /
r4 -> array_buff[0] = 0x03;r5 -> array_buff[1] = 0x04 /
(使用STM指令将多个值写入内存。STM指令将R4,R5寄存器的值0x3和0x4存入R1指向的内存空间中。由于之前我们让R1指向 array_buff的第一个元素,所以指令执行后 array_buff[0] = 0x00000003 ,array_buff[1] =0x00000004。如果没有特别说明,LDM和STM指令操作的基本单位是一个字(32位等于4个字节))
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分别包含了 0x3,0x4,0x5 ,内存地址0x000100D0, 0x000100D4,和 0x000100D8中也包含了0x3,0x4,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 */
(LDMIB指令先将源地址增加4字节(一个字),然后开始载入数据。该方法仍能让我们载入一串前向数据,但第一个数据的起始地址相较源地址有4个字节的偏移。这就是为什么我们用LDMIB指令将内存中的第一个元素载入R4后,R4是0x04(word[4]),而不是R0指向的0x3(word[3])

  执行之后,寄存器R4-R6存储了0x4,0x5,0x6, 0x100D4, 0x100D8, 和0x100DC也存储了 0x4,0x5,0x6。)

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 /
(使用LDMDA向相反方向执行运算。R0指向word[3],载入操作开始后,我们向后将 words[3], words[2]和words[1]载入R6, R5, R4。注意,连寄存器都是反着被载入的。所以指令将 R6赋值为0x00000003, R5赋值为0x00000002, R4赋值为0x00000001。这里的逻辑是,每次载入操作完成后向后减少内存地址所以是反向赋值。)
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 inother words - array_buff[0] */

.word array_buff+8           /* address of array_buff[2] */
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。