ARM寻址方式

所谓寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式。

ARM处理器的寻址方式

目前ARM处理器支持9种寻址方式,分别是立即数寻址、寄存器寻址、寄存器偏移寻址、寄存器间接寻址、基址变址寻址、多寄存器寻址、相对寻址、堆栈寻址和块拷贝寻址

1. 立即数寻址

也叫立即寻址,是一种特殊的寻址方式,操作数本身包含在指令中,只要取出指令也就取到了操作数。这个操作数叫做立即数,对应的寻址方式叫做立即寻址。例如:

MOV R0,#64     ;R0  ← 64
ADD R0, R0, #1  ;  R0   ← R0 + 1
SUB R0, R0, #0X3D  ;  R0   ← R0 – 0X3D

在立即数寻址中,要求立即数以“#”为前缀,对于以十六进制表示的立即数,还要求在“#”后加上“0X”或“&”或”0x“。

在ARM处理器中,立即数必须对应8位位图格式即立即数是一个在16位或32位的寄存器中的8bit常数,经循环移动偶数位得到。合法的立即数必须能够找到得到它的那个常数,否则这个立即数就是非法的。

例如:0X80是合法的,它可以通过0X80向左或向右移动0位得到,由于8位的常数都可以由其自身移动0位得到,因此8位的立即数都是合法的

0X03F8也是合法的,把它写成二进制形式为:0011 1111 1000,可以看出如果使用0XFE这个8位的常数在16位寄存器中循环左移2位就可以得到0X03F8。

判断一个立即数是否合法可以用以下的办法:即对于这个立即数进行循左移或右移操作,看看经过移动偶数位后,是否可以得到一个不大于0XFF的立即数(即不超过8位的立即数),如果可以得到,这个立即数就是合法的,否则就是非法的。象0X1010、0X1FA、0X1FF都是不合法的。

2. 寄存器寻址

寄存器寻址就是利用寄存器中的数值作为操作数,也称为寄存器直接寻址。

例如:ADD R0,R1, R2         ;R0  ← R1 + R2

该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。

这种寻址方式是各类微处理器经常采用的一种方式,也是执行效率较高的寻址方式。

3. 寄存器间接寻址

寄存器间接寻址就是把寄存器中的值作为地址,再通过这个地址去取得操作数,操作数本身存放在存储器中

例如:
LDR R0,[R1]
;R0 ←[R1],以寄存器R1的值作为操作数的地址,把取得操作数传送到R0中
ADD R0,R1,[R2]
;R0 ←R1 + [R2],以寄存器R2的值作为操作数的地址,取得操作数后与R1相加,结果存入寄存器R0中。

4. 寄存器偏移寻址

这是ARM指令集特有的寻址方式,它是在寄存器寻址得到操作数后再进行移位操作,得到最终的操作数。

例如:
MOV R0,R2,LSL  #3   ;R0 ← R2 * 8 ,R2的值左移3位,结果赋给R0。
MOV R0,R2,LSL  R1 ;R2的值左移R1位,结果放入R0。

可采用的移位操作如下:

LSL:逻辑左移(Logical Shift Left),寄存器中字的低端空出的位补0。
LSR:逻辑右移(Logical Shift Right),寄存器中字的高端空出的位补0。
ASL:算术左移(Arithmetic Shift Left),和逻辑左移LSL相同。
ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即如果源操作数是正数,则字的高端空出的位补0,否则补1。
ROR:循环右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。
RRX:带扩展的循环右移(Rotate Right eXtended),操作数右移一位,高端空出的位用进位标志C的值来填充,低端移出的位填入进位标志位。

5. 寄存器基址变址寻址

寄存器基址变址寻址又称为基址变址寻址,它是在寄存器间接寻址的基础上扩展来的。它将寄存器(该寄存器一般称作基址寄存器)中的值与指令中给出的地址偏移量相加,从而得到一个地址,通过这个地址取得操作数。

例如:
LDR R0,[R1,#4]
;R0 ←[R1 + 4],将R1的内容加上4形成操作数的地址,取得的操作数存入寄存器R0中。
LDR R0,[R1,#4]!
;R0 ←[R1 + 4]、R1 ←R1 + 4,将R1的内容加上4形成操作数的地址,取得的操作数存入寄存器R0中,然后,R1的内容自增4个字节。其中!表示指令执行完毕把最后的数据地址写到R1。
LDR R0,[R1,R2]
;R0 ←[R1 + R2],将寄存器R1的内容加上寄存器R2的内容形成操作数的地址,取得的操作数存入寄存器R0中。
STR R0, [R1,#-4]
;R0→[R1 -4],将R1中的数值减4作为地址,把R0中的数据存放到这个地址中。
LDR R0,[R1],#4    ;R0 ←[R1]、R1 ←R1+4

6. 多寄存器寻址

这种寻址方式可以一次完成多个寄存器值的传送。例如:

LDMIA  R0,{R1,R2,R3,R4}
LDM:Load Data from Memory to Register.
;R1←[R0],R2←[R0+4],R3←[R0+8],R4←[R0+12]
该指令的后缀IA表示在每次执行完加载/存储操作后,R0按字长度增加,因此,指令可将连续存储单元的值传送到R1~R4。
LDMIA  R0,{R1-R4}  ;功能同上。
STMIA   R0!,{R3-R6,R10};将 R3-R6,R10的值保存到 R0 指向的地址,过程中R0 自动加 1

使用多寄存器寻址指令时,寄存器子集的顺序如果由小到大的顺序排列,可以使用“-”连接,否则,用“,”分隔书写。

7. 相对寻址

相对寻址是一种特殊的基址寻址,特殊性是它把程序计数器PC中的当前值作为基地址,语句中的地址标号作为偏移量,将两者相加之后得到操作数的地址

BL   NEXT  ;相对寻址,跳转到NEXT处执行。
……
……
NEXT
……

8. 堆栈寻址

堆栈是一种数据结构,按先进后出(First In Last Out,FILO)的方式工作,使用堆栈指针(Stack Pointer, SP)指示当前的操作位置,堆栈指针总是指向栈顶

根据堆栈的生成方式不同,可以把堆栈分为递增堆栈和递减堆栈两种类型。如下图所示:

l 递增堆栈:向堆栈写入数据时,堆栈由低地址向高地址生长。

l 递减堆栈:向堆栈写入数据时,堆栈由高地址向低地址生长。

同时,根据堆栈指针(SP)指向的位置,又可以把堆栈分为满堆栈(Full Stack)和空堆栈(Empty Stack)两种类型。

l 满堆栈(Full Stack):堆栈指针指向最后压入堆栈的数据。满堆栈在向堆栈存放数据时的操作是先移动SP指针,然后存放数据。在从堆栈取数据时,先取出数据,随后移动SP指针。这样保证了SP一直指向有效的数据。

l 空堆栈(Empty Stack):堆栈指针SP指向下一个将要放入数据的空位置。空堆栈在向堆栈存放数据时的操作是先放数据,然后移动SP指针。在从堆栈取数据时,是先移动指针,再取数据。这种操作方式保证了堆栈指针一直指向一个空地址(没有有效数据的地址)。

上述两种堆栈类型的组合,可以得到四种基本的堆栈类型,即:

满递增堆栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生长。
满递减堆栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生长。
空递增堆栈(EA):堆栈指针指向下一个将要压入数据的地址,且由低地址向高地址生长。
空递减堆栈(ED):堆栈指针指向下一个将要压入数据的地址,且由高地址向低地址生长。
堆栈寻址举例如下:

STMFD  SP!,{R1-R7, LR}
STM: Store Data From register to Stack (Memory).
;将R1-R7, LR压入堆栈。满递减堆栈。
LDMED  SP!,{R1-R7, LR}
;将堆栈中的数据取回到R1-R7, LR寄存器。空递减堆栈。

9. 块拷贝寻址

块拷贝寻址用于寄存器数据的批量复制,它实现从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器传送数据。块拷贝寻址与堆栈寻址有所类似。两者的区别在于:堆栈寻址中数据的存取是面向堆栈的,块拷贝寻址中数据的存取是面向寄存器指向的存储单元的

在块拷贝寻址方式中,基址寄存器传送一个数据后有4种增长方式,即:

IA:每次传送后地址增加4;(Increment After Operating)
IB:每次传送前的地址增加4;(Increment Before Operating)
DA:每次传送后地址减少4;(Decrement After Operating)
DB:每次传送前地址减少4。(Decrement Before Operating)
对于32位的ARM指令,每次地址的增加和减少的单位都是4 个字节单位。

例如:

STMIA  R0!,{R1—R7}
;将R1-R7的数据保存到R0指向的存储器中,存储器指针在保存第一个值之后增加4,向上增长。R0作为基址寄存器。
STMIB  R0!,{R1—R7}
;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加4,向上增长。R0作为基址寄存器。
STMDA  R0!,{R1—R7}
;将R1-R7的数据保存到R0指向的存储器中,存储器指针在保存第一个值之后减少4,向下减少。R0作为基址寄存器。
STMDB  R0!,{R1—R7}
;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前减少4,向下减少。R0作为基址寄存器。

ARM指令中{!},为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。

{^}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。

LDMIA R0,{R1,R2,R3,R4}

与LDM IA R0!,{R1,R2,R3,R4}的区别?

前一条指令,执行完毕之后,R0的值保持不变;后一条指令执行完毕之后,R0的值发生了变化。

<think>好的,我需要回答用户关于ARM架构寻址方式的问题。首先,我需要回忆ARM架构中的寻址模式,并确保信息准确。用户可能希望了解不同的寻址方式及其应用场景。 首先,ARM寻址方式可以分为数据处理指令和内存访问指令两大类。数据处理指令如加减乘除通常涉及寄存器或立即数。内存访问指令如LDR和STR则有更多寻址模式,比如基址寻址、前变址、后变址等。 然后,我需要组织这些信息,按照用户的要求使用正确的中文和LaTeX格式。注意行内公式用$...$,独立公式用$$...$$,并检查语法是否正确。例如,基址寻址的偏移量可以用$[R1, #4]$表示。 接下来,生成相关问题。问题要覆盖寻址方式的应用、优化、比较和具体架构版本的影响。比如,不同ARM版本对寻址方式的扩展,如ARMv8中的变化。 还要注意引用部分,用户提供的引用中有提到AAPCS、ARMv7-A、ARMv8-A和NEON指令集。虽然主要关于寻址方式,但可以适当关联,比如在立即数范围受限时,如何通过多次加载来合成大立即数,这可能涉及过程调用标准中的寄存器使用约定[^1]。另外,ARMv7和ARMv8的差异可能影响寻址方式,比如CRC32扩展是否相关[^3],但可能这里更相关的是内存寻址模式的改进。NEON指令集的SIMD处理可能使用不同的寻址方式[^4],但用户的问题集中在寻址模式,所以可能只需简要提及。 需要确保回答结构清晰,分点说明每种寻址方式,并举例说明。同时,生成的三个相关问题要具体且与主题相关,帮助用户深入理解。 最后,检查LaTeX格式是否正确,是否有遗漏的符号或格式错误,比如确保所有数学表达式正确使用$符号,独立公式单独成段。例如,前变址寻址的示例可能需要用代码块展示,但用户示例中的Python代码是快速排序,这里可能需要用ARM汇编示例,但用户可能不需要具体代码,只需描述即可。 总结步骤:介绍寻址方式分类,详细说明每种类型,举例,引用相关知识点,生成相关问题。</think>### ARM架构中的寻址方式 ARM架构的寻址方式主要分为**数据处理指令寻址**和**内存访问指令寻址**两大类,具体模式如下: --- #### 1. 数据处理指令寻址 - **立即数寻址** 操作数直接包含在指令中,例如: $$ \text{ADD } R0, R1, \#0x10 $$ 表示将$R1 + 0x10$的结果存入$R0$。 **限制**:立即数需满足特定编码格式(如8位常数+4位移位)[^1]。 - **寄存器寻址** 操作数直接来自寄存器,例如: $$ \text{SUB } R2, R3, R4 $$ 表示$R3 - R4$的结果存入$R2$。 - **寄存器移位寻址** 操作数为寄存器的值经过移位后的结果,例如: $$ \text{MOV } R5, R6, \text{LSL} \#2 $$ 表示将$R6$左移2位后存入$R5$。 --- #### 2. 内存访问指令寻址(LDR/STR) - **基址寻址(Base Addressing)** 通过基址寄存器加偏移量访问内存,例如: $$ \text{LDR } R0, [R1, \#4] $$ 表示加载地址为$R1 + 4$处的数据到$R0$。 - **前变址寻址(Pre-indexed)** 先更新基址寄存器再访问内存,例如: $$ \text{LDR } R0, [R1, \#4]! $$ 执行后$R1$的值变为$R1 + 4$。 - **后变址寻址(Post-indexed)** 先访问内存再更新基址寄存器,例如: $$ \text{LDR } R0, [R1], \#4 $$ 加载$R1$指向的数据到$R0$后,$R1$自增4。 - **带偏移的寄存器寻址** 偏移量可以是另一个寄存器或立即数,例如: $$ \text{STR } R2, [R3, R4] $$ 表示将$R2$存入地址$R3 + R4$处。 --- #### 3. 其他特殊寻址 - **PC相对寻址** 用于跳转指令(如B、BL),通过计算与PC的偏移量确定目标地址[^1]。 - **多寄存器寻址** 如LDM/STM指令可同时加载/存储多个寄存器,支持栈操作模式(如FD、ED等)[^1]。 --- ### 应用场景与优化 - **立即数寻址**适用于小常数运算,但需注意范围限制(如ARMv7中立即数范围较窄)[^2]。 - **基址变址寻址**广泛用于数组和结构体访问,后变址模式适合循环遍历[^1]。 - **PC相对寻址**是实现位置无关代码(PIC)的关键,常用于动态链接库[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值