【ARM扩展资料】数据寻址
文章目录
一、寄存器寻址
A64指令的目的操作数采用寄存器寻址,常表达为Rd,是31个64(和32)位通用寄存器之一。大多数指令的源操作数之一也是寄存器寻址,常表达为Rn,还是是31个64(和32)位通用寄存器之一。寄存器寻址有时还可以是堆栈指针SP(WSP),或者零值寄存器XZR(WZR)。
第2个源操作数oprand2有多种寻址方式,可以是立即数寻址、寄存器寻址,在存储器访问指令中是存储器寻址。oprand2采用寄存器寻址时,常用Rm表示通用寄存器之一,还可以对Rm寄存器内容进行移位和扩展,也就是ARM处理器所特有的寄存器移位寻址和寄存器扩展寻址。
1. 寄存器移位寻址
oprand2形式是:Rm{, shift imm6}
。
其中,shift表示AArch64具有的4种寄存器移位操作:逻辑左移LSL(Logical Shift Left),逻辑右移LSR(Logical Shift Right),算术右移ASR(Arithmetic Shift Right),循环右移ROR(Rotate Right)。移位次数“imm6”对64位操作是0~63,而32位操作是0~31。
寄存器移位寻址主要应用于加减法指令(仅支持LSL、LSR和ASR移位)和逻辑运算指令。例如:
ADD Rd, Rn, Rm{, shift imm6} // 加法:Rd = Rn + Rm(可选移位)
SUB Rd, Rn, Rm{, shift imm6} // 减法:Rd = Rn - Rm(可选移位)
寄存器移位增强了指令功能,使得在进行加减运算的同时,还能实现移位操作。
2. 寄存器扩展寻址
oprand2形式是:Rm{, extend imm3}
。
其中,extend表示对寄存器Rm扩展,扩展后还可以左移0~4位(imm3)。AArch64支持的寄存器扩展操作,分成两类:
-
(1)无符号数的零位扩展:UXTB和UXTH分别把Wm的低字节和低半字数据进行零位扩展。
-
(2)有符号数的符号扩展:SXTB、SXTH和SXTW依次把Wm的低字节、低半字和字数据进行符号扩展。
寄存器扩展寻址主要应用于加减指令,可以利用寄存器扩展功能将位数较少的数据进行位扩展使两者位数相同,然后进行参与运算。例如:
ADD Rd|SP, Rn|SP, Rm{, extend imm3} // 加法:Rd = Rn + Rm(可选扩展)
SUB Rd|SP, Rn|SP, Rm{, extend imm3} // 减法:Rd = Rn - Rm(可选扩展)
实际上,A64指令集还有位扩展指令别名,其助记符与这里符号一样。
二、存储器寻址
A64指令不支持存储器的直接寻址,而是采用间接寻址。A64指令集的存储器地址由一个64位通用寄存器(称为基址寄存器)和可选的偏移量(立即数或者寄存器表达)组成。
1. 寄存器间接寻址
基址寄存器只是64位通用寄存器Xn或者堆栈指针SP,并加中括号表示间接寻址:
LDR Rt,[Xn|SP] ; Rt ← [Xn|SP]
例如:
ldr w2, [x1] // 32位数据载入:w2 ← [x1]
ldr x4, [x3] // 64位数据载入:x4 ← [x3]
2. 带立即数偏移量的寄存器间接寻址
存储器地址由基址寄存器加立即数表达的偏移量组成:
LDR Rt,[Xn|SP, imm12] ; Rt ← [Xn|SP + imm12]
imm12是一个12位无符号数表达的地址偏移量,对32位指令需是0~16380之间4的倍数,对64位指令需是0~32760之间8的倍数。4或8倍数是为了对齐存储器地址:
ldr w6, [x1, 4] // 32位数据载入:w6 ← [x1 + 4]
ldr x8, [x1, 240] // 64位数据载入:x8 ← [x3 + 240]
3. 后索引寻址(Post-index)
后索引寻址方式的指令具有两个功能:先通过[Xn|SP]间接寻址访问存储器内容,之后将Xn|SP加上偏移量更新Xn|SP的地址:
LDR Rt,[Xn|SP], imm9 ; Rt ← [Xn|SP], Xn|SP = Xn|SP + imm9
其中,偏移量imm9是一个字节的有符号数,数据范围为-256~255。例如:
ldr x11, [x3], 8 // x11 ← [x3],x3 = x3 + 8
4. 前索引寻址(Pre-index)
前索引寻址方式的指令也具有两个功能:先将Xn|SP加上偏移量更新Xn|SP的地址,然后用[Xn|SP]间接寻址访问存储器内容:
LDR Rt,[Xn|SP, imm9]! ; Rt ← [Xn|SP + imm9], Xn|SP = Xn|SP + imm9
为了有别于立即数偏移量的寄存器间接寻址,最后要添加“!”。例如:
ldr x12, [x3, -8]! // x12 ← [x3 - 8],x3 = x3 - 8
5. 带寄存器偏移量的寄存器间接寻址
地址偏移量保存于通用寄存器,与基址寄存器一起构成存储器地址:
LDR Rt,[Xn|SP, Wm|Xm{, extend 0|2|3}] ; Rt ← [Xn|SP + Wm|Xm(可选扩展)]
extend表示对偏移量进行移位或扩展,默认是左移LSL,对32位指令可以左移0或2位(乘4),对64位指令可以左移0或3位(乘8)。如果是32位寄存器Wm,extend需要使用UXTW零位扩展或SXTW符号扩展为64位,并支持2或3位的左移操作:
ldr x22, [x3, w5, sxtw] // 64位载入指令:x22 ← [x3 + 符号扩展w5]
ldr x23, [x3, w5, uxtw 3] // 64位载入指令:x23 ← [x3 + 零位扩展w5×8]