arm 汇编指令:内存访问方式 、STR 、LDR 指令

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/eibo51/article/details/36670929

Memeory accesses(内存访问的方式)

通常有以下三种方式,允许用作内存访问指令:

《1》Offset addressing (偏移寻址)

汇编语法格式:

[ <Rn> , <offset>]

内存访问地址值(memory)= 偏移地址(offset) + 基址寄存器( <Rn>)的值 。这种方式基址寄存器(<Rn>)值没有变化

《2》Pre-indexed addressing(带前索引寻址)

汇编语法格式:

【<Rn>,  <offset>]!

内存访问地址值(memory)= 偏移地址(offset) + 基址寄存器(<Rn>)的值 。此方式基址寄存器(<Rn>)的值 = 内存访问地址值(memory),在写入内存前发生变化(故名前索引)。

《3》Post-indexed addressing (带后索引寻址)

汇编语法格式:

 [<Rn>], <offset>

内存访问地址值(memory)= 基址寄存器( <Rn>)的值 。此方式基址寄存器(<Rn>)的值 = 偏移地址(offset) + 基址寄存器()的值,在写入内存后发生变化(故名后索引)。

在上面的各种情况中,<Rn> 是基址寄存器,<offset> 是偏移量,<offset > 可以用以下三种方式表示

1)立即数,例如《imm8)or (imm10)  or <imm 12>;

2)  索引寄存器,<Rm>内存访问地址值(memory)(内存访问地址值(memory)就是读取该寄存器的值,作为偏移量  索引寄存器,<Rm>内存访问地址值(memory)(内存访问地址值(memory)就是读取该寄  索引寄存器,<Rm>内存访问地址值(memory)(内存访问地址值(memory)就是读取该寄);

3)带移位索引寄存器,例如 <Rm>, LSL #<shift> (此就是Rm的值向左移动#<shift>位作为偏移量(offset));

介绍上述内存访问指令,主要是下面的指令需要用到。

STR(立即数,thumb/ARM)

概述:STR(立即数) 指令计算出从基址寄存器的数值和立即数的偏移(通过这,得出内存(memory)地址),然后从一个寄存器(register)读取它的值(store)到内存(memory)中。

汇编语法格式:

STR{<c>}{<q>} <Rt>, [ <Rn>  {, #+/-<imm>}] 

首先宏观分析下, 将"{}" 的内容都忽略掉,可以得到如下结构:

STR <Rt>, [ <Rn>]

此条汇编语句可以得到如下的运算: 由Rn寄存器的值得到内存地址(memory),memory 内存地址值=<Rt>(换句话,将<Rt> 寄存器的值,store(存储)到memory所在的地址单元内中)。

接着扩展下,将”{, #+/-<imm>}“部分加入,可以得到如下结构:

STR <Rt>, [ <Rn>  , #imm]

此部分的语法 [ <Rn>  , #imm] 就是上面Memeory accesses(内存访问的方式)提到的Offset addressing (偏移寻址),本质就是计算出内存地址 啦,不再赘述。

再接着扩展下,将“ {<c>}” 部分加入, 可以得到如下结构:

STRAL <Rt>,  [<Rn>, #imm]  @AL(Always 可以省略的),这是默认不加此部分的语法,c 指conditional ,没加就是alway unconditional 无条件执行

STRLT  <Rt>,  [<Rn>, #imm]  @ LT signed less than 有符合数小于条件满足才能执行

STRLE  <Rt>, [<Rn>, #imm]   @ LE signed less than or equal 有符号数小于或等于条件满足均可执行

STREQ  <Rt>, [<Rn>, #imm]  @ Equal 有符号数和无符号数满足等于条件才可执行

其它具体参考ARM 语法手册。

最后接着扩展下, 将“{<q>}"部分加入, 可以得到如下结构:

STRAL.N  <Rt>, 【<Rn>, #imm]

STRAL.W  <Rt>, [<Rn>, #imm]

q 是qulitifiers 的缩写,

.N 是Narrow , 意指汇编器必须为这条指令选择一个16位的编码模式。如果不能办到,就会出现汇编器错误。

.W 是wide。指定汇编器必须为这条指令选择一个32位的编码模式。如果办不到,汇编器报错。

如果忽略掉此部分,汇编可以选择16位或32位的编码,如果二者均可,他会选择16位的编码。

STR{<c>}{<q>} <Rt>, [<Rn>, #+/-<imm>]! @ 与前述区别就是上面Memeory accesses(内存访问的方式)提到的Pre-indexed addressing(带前索引寻址)
STR{<c>}{<q>} <Rt>, [<Rn>],#+/-<imm> @与前述区别就是上面Memeory accesses(内存访问的方式)提到的Post-indexed addressing (带后索引寻址)

STR (register)

汇编语法
STR{<c>}{<q>} <Rt>, [<Rn>, <Rm>{, <shift>}] 
STR{<c>}{<q>} <Rt>, [<Rn>, <Rm>{, <shift>}]!
STR{<c>}{<q>} <Rt>, [<Rn>], <Rm>{, <shift>} 

此语法结构和前述不同之处,就是此处用 寄存器来传递offset ,而非立即数来传递。
offset = <Rn> + (<Rm> 逻辑向左( LSL) 或逻辑向右(LSR)或者算术向右(ASR) 或者循环向右(ROR)移动 (shift )n位,或循环带进位(RRX)向右移动1位,)

这样就可变形为:

STR{<c>}{<q>} <Rt>, [<Rn>,#offset]

STR{<c>}{<q>} <Rt>, [<Rn>, #offset]!

STR{<c>}{<q>} <Rt>, #offset


LDR(立即数,thumb/ARM)

概述:LDR 从基址寄存器Rn 的和立即数的偏移之和 得出内存地址的位置,从内存地址里面Load(装载)一个字的值写到 Rt 寄存器。

LDR{<c>}{<q>} <Rt>, [<Rn> {, #+/-<imm>}]

LDR{<c>}{<q>} <Rt>, [<Rn> , #+/-<imm>]!

LDR{<c>}{<q>} <Rt>, [<Rn> ] , #+/-<imm>

 内存地址(memory)的分析和STR 类似,不同是这些指令是将内存(memory)的值Load(装载)到寄存器(Rt)中去的。

LDR(register,thumb)

概述: Load Register 从基址寄存器的值和一个偏移寄存器的值计算出内存的地址,从该地址单元读出一个字的数值,将它写入寄存器中。

LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, <shift>}]  @在thumb指令中,只能选择偏移寄存器Rm的值到基址寄存器Rn中,而不能

LDR(register,ARM)

概述: Load Register 从基址寄存器的值和一个偏移寄存器的值计算出内存的地址,从该地址单元读出一个字的数值,将它写入寄存器中。

LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]

LDR{<c>}{<q>}  [<Rt>, [ <Rn>,{+/-} <Rm>{, <shift>}]!

LDR{<c>}{<q>} <Rt>,[<Rn>] ,{+/'-} <Rm>{,<shift>}

LDR(literal)

 概述:从PC的值和一个偏离立即数计算出内存的地址值,从此处内存中load(加载)一个字,把它写入到寄存器中。

汇编语法

LDR{<c>} {<q>}  <Rt>, <label >          @ label  就是一个指定的标号

LDR{<c>} {<q>}  <Rt>, [PC, #+/-<imm>]



2014.10.26

ps:

str理解为 store a register to "value" ==》此处的“”value“就是“memory”(内存也就是芯片的RAM)

ldr理解为 load  " value "  to a register

stm :store multiple registers to ”someplace“ ==》此处的"someplace"  就是 “block memory”(某块连续的内存)

ldm: load multiple registers from “someplace”

2017.01.05

memory-reads <=> loads

memory-writes<=> stores

wiwa

展开阅读全文

没有更多推荐了,返回首页