【基于Android的ARM汇编语言系列】之四:ARM处理器的寻址方式

时间:2021-07-13 01:21:25

作者:郭嘉
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWell

【基于Android的ARM汇编语言系列】章节列表

【基于Android的ARM汇编语言系列】之一:ARM汇编语言开篇
【基于Android的ARM汇编语言系列】之二:C/C++程序生成ARM汇编程序的过程分析
【基于Android的ARM汇编语言系列】之三:ARM汇编语言程序结构
【基于Android的ARM汇编语言系列】之四:ARM处理器的寻址方式
【基于Android的ARM汇编语言系列】之五:ARM指令集与Thumb指令集
【基于Android的ARM汇编语言系列】之六:NEON指令集与VFP指令集

处理器的寻址方式是通过指令给出的地址码字段来寻找真实操作数地址的方式,ARM处理器支持9中寻址方式。

一 立即寻址

立即寻址指令后面的地址码部分为立即数(常量或常数),立即寻址多用于给寄存器赋值。

举例

MOV RO, #1234

指令执行后,R0=1234。

二 寄存器寻址

寄存器寻址中,操作数在寄存器中,指令执行时直接从寄存器中取值进行操作。

举例

MOV R0, R1

指令执行后,R0=R1。

三 寄存器移位寻址

寄存器移位寻址是ARM指令集特有的寻址方式,和寄存器寻址类似,只是操作前需要对寄存器操作数进行移位操作。

  • LSL:逻辑左移,移位后寄存器空出的低位补0。
  • LSR:逻辑右移,移位后寄存器空出的高位补0。
  • ASR:算术右移,移位过程中,符号位保持不变,如果源操作数是正数,则空出的高位补0,否则补1.
  • ROR:循环右移,移位后移除的低位填入空出的高位。
  • RRX:带扩展的循环右移,操作数右移一位,移位空出的高位用C标志的值填充。

举例

MOV R0, R1, LSL #2

R1寄存器左移两位赋值给R0,指令执行后,R0=R1*4。

四 寄存器间接寻址

寄存器间接寻址中地址码给出的寄存器是操作数的地址指针,所需的操作数保存在寄存器指定的存储单元中。

举例

LDR R0, [R1]

将R1寄存器的数值作为地址,取出此地址中的值赋给R0寄存器。

五 基址寻址

基址寻址是将地址码给出的基址寄存器和偏移量相加,形成操作数的有效地址,所需的操作数保存在有效地址所指向的存储单元中。基址寻址多用于查表和数组访问等操作。

举例

LDR R0, [R1, #-4]

将寄存器R1的数组减去4作为地址,取出此地址中的值赋值给R0。

六 多寄存器寻址

多寄存器寻址一条指令最多可以完成16个通用寄存器的传送。

举例

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

LDM是数据加载指令,指令的后缀IA表示每次执行完加载操作后R0寄存器的值自增1个字。指令执行后,R1=[R0],R2=[R0+#4],R3=[R0+#8],R4=[R0+#12]。

七 堆栈寻址

堆栈寻址是ARM处理器特有的一种寻址方式,堆栈寻址使用特定的指令来完成。

  • LDMFA/STMFA
  • LDMEA/STMEA
  • LDMFD/STMFD
  • LDMED/STMED

举例

STMFD SP1, {R1-R7, LR}

将R1-R7,LR入栈,多用于保存子程序现场。

LDMFD SP1, {R1-R7, LR}

将数据出栈,放入R0-R7,LR寄存器,多用于恢复程序现场。

八 块拷贝寻址

块拷贝寻址可实现连续地址数据从存储器的某一位置拷贝到另一位置。

  • LDMIA/STMIA
  • LDMDA/STMDA
  • LDMIB/STMIB
  • LDMDB/STMDB

举例

LDMIA R0!, {R1-R3}

从R0寄存器的存储单元中读取3个字到R1-R3寄存器中。

STMIA R0!, {R1-R3}

存储在R1-R3寄存器的内容到R0指向ed存储单元。

九 相对寻址

相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到的操作数作为有效地址。

举例

BL NEXT
...
NEXT:
...

BL NEXT是跳到NEXT标号处执行,这里的BL就是采用相对寻址,标号NEXT是偏移量。