有的时候,CPU可能会遇到 a++; b++; c++,这个时候为了提升效率,CPU可能会一次将多个寄存器里的变量保存到内存中。这个时候之前介绍的 LDR / STR 指令虽然也能实现,但只能操作一个寄存器的读写。
因此,考虑到这点,下面介绍多个寄存器的读写指令
- 将多个寄存器的数据写入到内存 —— STM指令
- 从内存中读取数据保存到多个寄存器 —— LDM指令
目录
1、基本读写指令
(1) STM 指令
STM指令的作用是将多个寄存器的数据依次保存到内存中的某一个位置。
指令格式:
- STM 第一操作寄存器, {起始寄存器 - 末尾寄存器}
- STM 第一操作寄存器, {寄存器1, 寄存器2, ...}
- MOV R1, #0x1
- MOV R2, #0x2
- MOV R3, #0x3
- MOV R4, #0x4
- MOV R11, #0x40000000
-
- STM R11, {R1-R4} @ 将R1-R4寄存器中的数据保存到以R11为起始位置的内存中(R11地址不随内存自增)
-
- STM R11, {R1, R2, R3, R4} @ 与上面等价(R11地址不随内存自增,即R11就是起始地址)
-
- STM R11!, {R1, R2, R3, R4} @ 在R11的后面加上“ ! ”可以让R11中的地址随内存的存储位置自增变化
注意:花括号{ }中的寄存器编号顺序建议是升序,即便是乱序或者是降序,会优先将寄存器编号较小的保存到内存。
(2) LDM 指令
LDM指令的作用是将内存中一段地址的数据保存到多个寄存器。(类似用法及注意事项可以参考STM指令)
指令格式:
- LDM 第一操作寄存器, {起始寄存器 - 末尾寄存器}
- LDM 第一操作寄存器, {寄存器1, 寄存器2, ...}
- MOV R1, #0x1
- MOV R2, #0x2
- MOV R3, #0x3
- MOV R4, #0x4
- MOV R11, #0x40000000
- STM R11, {R1-R4}
-
- LDM R11, {R6-R9} @ 将内存中以R11为起始地址的数据读取到 R6-R9 寄存器
- LDM R11, {R6, R7,R8,R9} @ 与上述写法等价
注意:读取的字节大小看有多少个寄存器,每个寄存器默认保存4个字节的数据。
2、多寄存器的内存读写方式
默认情况下,是以某一个寄存器指向的地址为起始地址,自低地址向高地址写入 / 读取。可以通过在上述基本指令的后面加后缀来改变内存的读写方式,比如自高地址向低地址写入、从起始位置的下一个地址开始写入。
下面以写内存为例。
- MOV R1, #0x1
- MOV R2, #0x2
- MOV R3, #0x3
- MOV R4, #0x4
- MOV R11, #0x40000020
- STM R11, {R1-R4} @ 起始地址为 R11
(1) 后缀 IA(默认)
IA 表示 Increase After,先将数据保存到内存,然后再让地址自增。STM默认采用的方式与STMIA达到的效果是一样的。
STMIA R11!, {R1-R4} @ 保存起始地址为 R11
注意:加“ ! ”了以后,寄存器中保存的地址会跟着内存的增长方向发生变化
(2) 后缀 IB
IA 表示 Increase Before,在写入内存之前先让R11自增4个字节,然后再开始存。
STMIB R11!, {R1-R4} @ 保存起始地址为 R11 + 4
(3) 后缀 DA
DA 表示 Decrease After,先将数据保存到内存,然后再让地址自减。(自高地址到低地址存储)
STMDA R11!, {R1-R4} @ 保存起始地址为 R11(自低地址向高地址存储)
(4) 后缀 DB
DB 表示 Decrease Before,在写入内存之前先让R11自减4个字节,然后再开始存。
STMDB R11!, {R1-R4} @ 保存起始地址为 R11 - 4(自低地址向高地址存储)
评论记录:
回复评论: