ARM 指令集概要

本文将介绍 ARM 指令的基本概念,包括指令的编码格式、指令的条件码、指令的寻址方式等。

1. ARM 指令集分类

ARM32 指令字长固定为 32 位,其编码格式如下:

31...28 27...25 24...21 20 19...16 15...12 11...0
cond 001 opcode S Rn Rd shift_operand

其中的符号说明如下:

  • cond:条件编码;
  • opcode:操作编码;
  • S:决定指令的操作是否影响 CPSR 的值;
  • Rn:包含第一个操作数的寄存器编码;
  • Rd:目标寄存器的编码;
  • shifter_operand:第二个操作数。

一条指令的语法格式如下:

<opcode>{<cond>}{S} <Rd>, <Rn>, <shifter_operand>

2. ARM 指令条件码

大多数 ARM 指令都可以有条件地执行,也就是根据CPSR中的条件标志位决定是否执行该指令。当条件满足时执行该指令,条件不满足时该指令被当作一条NOP指令,这时处理器进行判断中断请求等操作,然后转向下一条指令。

ARM 的条件编码域有 4 位,因此有 16 个条件码,具体编码如下:

条件码 助记符 含义 CPSR 条件标志位
0000 EQ 相等 Z=1
0001 NE 不相等 Z=0
0010 CS/HS 无符号数大于等于 C=1
0011 CC/LO 无符号数小于 C=0
0100 MI 负数 N=1
0101 PL 非负数 N=0
0110 VS 上溢出 V=1
0111 VC 没有上溢出 V=0
1000 HI 无符号数大于 C=1 且 Z=0
1001 LS 无符号数小于等于 C=0 或 Z=1
1010 GE 有符号数大于等于 N=1 且 V=1 或 N=0 且 V=0
1011 LT 有符号数小于 N=1 且 V=0 或 N=0 且 V=1
1100 GT 有符号数大于 Z=0 且 N=V
1101 LE 有符号数小于等于 Z=1 或 N!=V
1110 AL 无条件执行
1111 NV v5 以上版本无条件执行

3. ARM 数据处理指令寻址方式

通常数据处理指令的格式为:

<opcode>{<cond>}{S} <Rd>, <Rn>, <shifter_operand>

其中 <shifter_operand> 通常有下面 3 中格式:

立即寻址

这 12 位并非直接表示一个 12 位的整数,而是被分为两个部分:

  • 高 4 位:移位值 rotate_value,用于表示循环移位的次数;
  • 低 8 位:立即数 immediate_value,用于表示待移位的数值。

最终的操作数由该 8 位的立即数循环右移偶位数得到,循环右移的次数由该 4 位的移位值给出,即:

immediate = ue(immediate_value) ROR (2 * rotate_value)

可以注意到,2 * rotate_value 可以是 0-30 之间的偶数值,这使得该 12 位的立即寻址可以覆盖较广的数据范围。但是,并非所有的 32 位整数都能使用这种方法表示,如 0x1010xFF1 就不能使用这种方法表示,此时,汇编器会结合其他指令来实现这一功能。

一个合法的 32 位立即数可能有几种表示方法。一般情况下,ARM 汇编器会按照以下规则来生成立即数的指令编码:

  • 当立即数在 0x000xFF 范围中时,直接使用 immediate_value 进行表示;
  • 在其他情况下,使用 rotate_value 数值最小的编码方式。
寄存器寻址

在这种方式下,直接由 <shifter_operand> 字段给出寄存器地址,相应的寄存器内容即为操作数。

寄存器偏移寻址

在这种方式下,需要从<shifter_operand> 字段中解析出寄存器地址、移位操作编码、移位操作的次数,将寄存器中的数值进行移位后再进行后续的运算。

移位方式有以下几种:

  • 3b00x:LSL,逻辑左移;
  • 3b01x:LSR,逻辑右移;
  • 3b10x:ASR,算数右移;
  • 3b11x:ROR,循环右移;
  • 8b00000110:RRX,扩展的循环右移。

移位位数由立即数(3bxx0)或者寄存器(3bxx1)给出,即以下两种方式:

立即数方式
操作数的基本格式为 <Rm>,<shift_mode> #<shift_imm>,指令的编码格式为:

31...28 27...25 24...21 20 19...16 15...12 11...7 6...4 3...0
cond 000 opcode S Rn Rd shift_imm xx0 Rm

在这种方式下,生成操作数的方法为:取出 Rm 寄存器中的数值,进行移位操作,移位的次数为 shift_imm

寄存器方式
操作数的基本格式为 <Rm>,<shift_mode> <Rs>,指令的编码格式为:

31...28 27...25 24...21 20 19...16 15...12 11...8 7...4 3...0
cond 000 opcode S Rn Rd Rs 0xx1 Rm

在这种方式下,生成操作数的方法为:取出 Rm 寄存器中的数值,进行移位操作,移位的次数为 Rs 寄存器中的数值。

4. ARM 内存访问寻址方式

Load 指令用于从内存中读取数据放入寄存器中;Store 指令用于将寄存器中的数据保存到内存中。ARM 有两大类 Load/Store 指令:一类用于操作 32 位的字类型数据以及 8 位无符号的字节类型数据;另一类用于操作 16 位半字类型的数据以及 8 位的有符号字节类型的数据。

各种类型的 Load/Store 指令的寻址方式由两部分组成:一部分为一个的基址寄存器;另一部分为一个地址偏移量。基址寄存器可以为任一个通用寄存器;地址偏移量可以有以下 3 种格式:

  • 立即数;
  • 寄存器;
  • 寄存器偏移。

地址的计算方法有 3 种方式:

  • 偏移量方法。这种方法中,基址寄存器中的值和地址偏移量做加减运算,生成操作数的地址。
  • 事先更新方法。这种方法中,基址寄存器中的值和地址偏移量做加减运算,生成操作数的地址。指令执行后,这个生成的操作数地址被写入基址寄存器。
  • 事后更新方法。这种方法中,指令将基址寄存器的值作为操作数的地址执行内存访问。基址寄存器中的值和地址偏移量做加减运算,生成操作数的地址。指令执行后,这个生成的操作数地址被写入基址寄存器。

内存访问指令的基本格式为:

31...28 27 26 25 24 23 22 21 20 19...16 15...12 11...0
cond 0x I P B x W L Rn Rd address_mode
posted @ 2025-08-08 17:01  木杉的园子  阅读(89)  评论(0)    收藏  举报