本文声明:内容来源于网络,进行整合/再创作;部分内容由AI辅助生成。
Tips:本节知识分为上、下篇讲述,可通过专栏查找到对应文章。关于指令内容的讲述优先以AArch64执行状态为主,部分内容可能与AArch32类似。
寻址就是寻找指令中操作数的地址。存储单元中存放的数据信息大致可分为两大类:指令信息、操作数。两类信息的寻址方式既有相同之处,又各有特点。
寻址方式就是处理器根据指令中给出的地址信息来寻找有效地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。
数据处理指令的寻址方式
数据处理指令的基本语法格式:<opcode>{S} <Xd>, <Xn>, <shifter_operand>
|----------------------|-----------|--------------------------------------------------|---------------------------------------------------------------------------------|
| 语法成分 | 名称 | 说明 | 例子 |
| <opcode> | 操作码 | 告诉 CPU 执行什么运算。 | ADD (加法), SUB (减法), AND (逻辑与), ORR (按位或) |
| {S} (花括号表示可选的) | 条件码标志位更新 | 若带上 S,运算结果会影响 CPU 的条件码标志位 (零、负、进位等),通常用于后面的条件判断。 | SUBS 表示做减法,并且结果会更新标志;SUB 只做减法 |
| <Xd> | 目标寄存器 | 存放运算结果的寄存器。 | X0, X1 (AArch64状态下) R0, R1 (AArch32状态下) |
| <Xn> | 第一操作数 寄存器 | 参与运算的第一个数据来源,必须来自寄存器。 | X3, X5 R2, R7 |
| <shifter_ operand> | 灵活的 第二操作数 | 第二个参与运算的数据,可在运算前可以先被处理。 | 常见的形式: 立即数,如 #5 寄存器,如 X2 寄存器带移位 (先把值处理一下再算),如把 X2 里的值逻辑左移 2 位(相当于乘以4)X2, LSL #2 |
1、立即数寻址
AArch64下的汇编程序必须允许使用"#"引入立即数,而汇编语言则不要求。在AArch64汇编语言中的立即数前边可以加"#",也可以不加"#"。为了提高代码的可读性,AArch64反汇编程序都会在立即数前添加一个"#"。
指令示例(Xn代表使用AArch64下的寄存器组织):
MOV X0, #0xFF ; 将0xFF赋值给X0
ADD X1, X1, #1 ; X1 = X1 + 1
CMP X7, #2000 ; 将X7寄存器中的值和2000比较
ORR X9, X1, #0xFF ; 将X1中的低8位[7:0]的值(都是1)写到X9中
2、寄存器寻址
寄存器的值可以被直接用于数据操作指令,这种寻址方式是各类处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。
指令示例:
Cobol
MOV X2, X0 ; X0的值赋值给X2
ADD X4, X3, X2 ; X4 = X3 + X2
CMP X7, X8 ; 比较X7和X8的值
3、寄存器移位寻址
寄存器的值在被送到ALU(算数逻辑单元)之前,可先经过桶形移位寄存器的处理。预处理和移位发生在同一周期内,所以有效地使用移位寄存器,可以增加代码的执行效率。
指令示例:
ADD X2, X0, X1, LSR #5 ; X1中的值先右移5位,X2 = X0 + X1
MOV X1, X0, LSL #2 ; X0中的值先左移2位,结果赋值给X1
SUB X1, X2, X0, LSR #4 ; X0中的值先右移4位,X1 = X2 - X0
内存访问指令的寻址方式(AArch64下)
在AArch64指令集中的内存访问指令(Load/Store)寻址模式,是基于T32架构演进而来的,核心是使用64位通用寄存器Xn(n=0~30)或当前堆栈指针SP作为基址,具有立即数或寄存器偏移量方式。
Load/Store 寻址方式总览
|-------------|------------------|--------------------------|--------------------------------|
| 寻址方式 | 立即数偏移 | 寄存器偏移 | 扩展寄存器偏移 |
| 基址寄存器 (无偏移) | [base{, #0}] | - | - |
| 基址寄存器 (加偏移) | [base{, #imm}] | [base, Xm{, LSL #imm}] | [base, Wm, {S|U}XTW {#imm}] |
| 前索引寻址 | [base, #imm]! | - | - |
| 后索引寻址 | [base], #imm | [base], Xm | - |
| PC 相对寻址 | label | - | - |
注意事项
- 花括号{...}内的内容表示可选的。
- 基址寄存器:所有寻址模式(除 PC 相对寻址外)都使用64位的通用寄存器或栈指针SP作为基址。
- 更新标志 !:在前索引寻址中,感叹号"!"明确表示将计算后的新地址写回基址寄存器,这是与 "基址寄存器(加偏移)" 的核心区别。
- 偏移缩放:寄存器偏移时,LSL #imm(左移)和 {S|U}XTW {#imm}(扩展并缩放)是对偏移量进行缩放的常用手段,以适应不同数据类型的访问(如按字节、半字、字寻址)。
- 指令支持:并非所有 Load/Store 指令都支持表中全部的寻址模式,具体需参考指令集手册。
Tips:更具体的Load/Store寻址方式在本节下篇,可在专栏文章里找到。