在本文档的汇编语法中,用 # 前缀表示立即值,用 & 表示十六进制值,用 % 表示二进制值,用 {花括号} 表示指令中可选的设置字段或位。下面表格中粗体的指令是核心 ARM 指令,其他的是值得包含的位和片段、移位选项和汇编器助记码(mnemonic)... 还列出了协处理器指令。但是用于 RISC OS 机器的 ARM 处理器不支持协处理器,只在一个可访问的芯片中提供了实际上的协处理器功能。其中包括设置 ARM、cache、MMU 的设施,等...
指令 | 意义 | 最早的 CPU / 注释 |
ADC | 带进位的加法 | - |
ADD | 加法 | - |
AND | 逻辑与 | - |
ASL | 算术左移 | 这是一个选项,不是指令 |
ASR | 算术右移 | 这是一个选项,不是指令 |
B | 分支 | - |
BIC | 位清除 | - |
BL | 带连接的分支 | - |
BX | 分支到 Thumb 代码 | StrongARM SA1110 ? |
CDP | 协处理器数据操作 | - |
CMN | 比较取负的值 | - |
CMP | 比较值 | - |
EOR | 异或两个值 | - |
LDC | 装载内存到协处理器 | - |
LDM | 装载多个寄存器 | - |
LDR | 装载寄存器 | - |
LDRB | 装载字节到寄存器 | - |
LDRH | 装载半字到寄存器 | StrongARM |
LDRSB | 装载有符号字节到寄存器 | StrongARM |
LDRSH | 装载有符号半字到寄存器 | StrongARM |
LSL | 逻辑左移 | 这是一个选项,不是指令 |
LSR | 逻辑右移 | 这是一个选项,不是指令 |
MCR | 协处理器寄存器传送 | - |
MLA | 带累加的乘法 | - |
MOV | 传送值/寄存器到一个寄存器 | - |
MRC | 协处理器寄存器传送 | - |
MRS | 传送状态标志到一个寄存器 | ARM 6 |
MSR | 传送一个寄存器的内容到状态标志 | ARM 6 |
MUL | 乘法 | - |
MVN | 传送取负的(值) | - |
ORR | 逻辑或 | - |
ROR | 循环右移 | 这是一个选项,不是指令 |
RRX | 带扩展的循环右移 | 这是一个选项,不是指令 |
RSB | 反向减法 | - |
RSC | 带借位的反向减法 | - |
SBC | 带借位的减法 | - |
SMLAL | 带累加的有符号长(64 位)乘法 | StrongARM |
SMULL | 有符号长(64 位)乘法 | StrongARM |
STC | 协处理器数据传送 | - |
STM | 存储多个寄存器 | - |
STR | 存储一个寄存器 | - |
STRB | 存储一个字节(从一个寄存器) | - |
STRH | 存储一个半字(从一个寄存器) | StrongARM |
STRSB | 存储一个有符号字节(从一个寄存器) | StrongARM |
STRSH | 存储一个有符号半字(从一个寄存器) | StrongARM |
SUB | 减法 | - |
SWI | 导致一个软件中断 | - |
SWP | 交换寄存器与内存 | ARM 3 |
TEQ | 测试等价(概念上的 EOR) | - |
TST | 测试并屏蔽(概念上的 AND) | - |
UMLAL | 带累加的无符号长(64 位)乘法 | StrongARM |
UMULL | 无符号长(64 位)乘法 | StrongARM |
ADR | 得到目标的地址(4K 之内) |
ADRL | 得到目标的地址(超过 4K) |
ALIGN | 把程序计数器设置到下个字的边界 |
DCx | 定义字节(B)、半字(W)、字(D)、字符串(S)、或浮点(F)值 |
EQUx | 定义字节(B)、半字(W)、字(D)、字符串(S)、或浮点(F)值 |
OPT | 选择汇编选项 |
ABS | 绝对值 |
ACS | 反余弦 |
ADF | 加法 |
ASN | 反正弦 |
ATN | 反正切 |
CMF | 比较浮点值 |
CNF | 比较取负的浮点值 |
COS | 余弦 |
DVF | 除法 |
EXP | 指数 |
FDV | 快速除法 |
FIX | 转换浮点值成整数 |
FLT | 转换整数成浮点值 |
FML | 快速乘法 |
FRD | 快速反向除法 |
LDF | 装载浮点值 |
LFM | 装载多个浮点值 |
LGN | 自然对数 |
LOG | 常用对数 |
MNF | 传送取负的值 |
MUF | 乘法 |
MVF | 传送值/浮点寄存器到一个浮点寄存器 |
NRM | 规格化 |
POL | 极化角 |
POW | 幂 |
RDF | 反向除法 |
RFC | 读 FP 控制寄存器 |
RFS | 读 FP 状态寄存器 |
RMF | 余数 |
RND | 舍入成整值 |
RPW | 反向幂 |
RSF | 反向减法 |
SFM | 存储多个浮点值 |
SIN | 正弦 |
SQT | 平方根 |
STF | 存储浮点值 |
SUF | 减法 |
TAN | 正切 |
URD | 非规格化舍入 |
WFC | 写 FP 控制寄存器 |
WFS | 写 FP 状态寄存器 |
本文档部分内容取自 ARM 汇编器手册。
ARM 可以与最多 16 个协处理器相接口(interface)。ARM3 和以后的处理器在 ARM 内有虚拟的协处理器来处理内部控制功能。而可获得的第一个协处理器是浮点处理器。这个芯片处理 IEEE 标准的浮点运算。定义了一个标准的 ARM 浮点指令集,所以编码可以跨越所有 RISC OS 机器。如果不存在实际的硬件,则这些指令被截获并由浮点模拟器模块(FPEmulator)来执行。程序不需要知道是否存在 FP 协处理器。唯一不同的是执行速度。
RISC OS 的 BASIC 汇编器,作为标准,不支持任何真实的浮点指令。你可以转换整数到你的实现定义的‘浮点’并用它们进行(最普通的定点)基本数学运算,但你不能与浮点协处理器交互并以‘固有的’方式来做这些事情。但是,扩展汇编器功能的补丁中包含了 FP 指令。
ARM IEEE FP 系统由 8 个高精度 FP 寄存器(F0 到 F7)。寄存器的格式是无关紧要的,因为你不能直接访问这些寄存器,寄存器只在它被传送到内存或 ARM 寄存器时是‘可见的’。在内存中,一个 FP 寄存器占用三个字,但因为 FP 系统把它重新装载到自己的寄存器中,这三个字的格式是无关紧要的。还有一个 FPSR (浮点状态寄存器),它类似于 ARM 自己的 PSR,持有应用程序可能需要的状态信息。可获得的每个标志都有一个‘陷阱’,这允许应用程序来启用或禁用与给定错误关联的陷阱。FPSR 还允许你得知在 FP 系统得不同实现之间的区别。还有一个 FPCR (浮点控制寄存器)。它持有应用程序不应该访问的信息,比如开启和关闭 FP 单元的标志。典型的,硬件有 FPCR 而软件没有。
FP 单元可以软件实现比如 FPEmulator 模块,硬件实现比如 FP 芯片(和支持代码),或二者的组合。二者的最好的例子是 Warm Silence Software 补丁,它允许 ARM FP 操作利用配备在 PC 协处理器卡上的 80x87 作为作为一个浮点协处理器。
计算的结果如同有无限的精度,接着被舍入成要求的精度。舍入方式有就近舍入,向正无穷(P)舍入, 向负无穷舍入(M), 或向零舍入。缺省的是就近舍入。如果不可抉择,则舍入到最近似的偶数。工作精度是 80 位,其组成是 64 位尾数,15 位指数,和一个符号位。在一些实现中对用单精度工作的指令提供了更好的性能 - 特别是完全基于软件的那些实现。
FPSR 包含 FP 系统所需的状态。总是提供 IEEE 标志,但只在一次 FP 比较操作之后才可获得结果标志。
浮点指令不应该用在 SVC 模式下。
FPSR 的低字节是例外标志字节。
6 4 3 2 1 0 FPSR: 保留 INX UFL OFL DVZ IVO
当引发一个例外条件的时候,把在位 0 到 4 中的适当的累计(cumulative)例外标志设置为 1。如果设置了相关的陷阱位,则按操作系统指定的方式把一个例外递送给用户程序。(注意在下溢的情况下,陷阱启用位的状态决定在什么条件下设置下溢标志。) 只能用 WFS 指令清除这些标志。
IVO - invalid operation 无效操作
在进行的操作的一个操作数是无效时设置 IVO。无效操作有:
DVZ - division by zero 除零
如果除数是零而被除数是一个有限的、非零的数则设置 DVZ 标志。如果禁用了陷阱则返回一个正确的有符号的无穷。还为 LOG(0) 和 LGN(0) 设置这个标志。如果禁用了陷阱则返回负无穷。
OFL - overflow 上溢
结果幅值超出目的格式最大的数的时候设置 OFL 标志,舍入的结果是指数范围无限大的(unbounded)。 因为在结果被舍入之后检测上溢,在一些操作之后是否发生上溢依赖于舍入模式。如果禁用了陷阱,要么返回一个有正确符号的无穷,要么返回这个格式的最大的有限数。这依赖于舍入模式和使用的浮点系统。
UFL - underflow 下溢
两个有关联的事件产生下溢:
依赖于 UFL 陷阱启用位的值,以不同的方式设置 UFL 标志。如果启用了陷阱,则不管是否有准确性损失极,在检测到极小值时就设置 UFL 标志。如果禁用了陷阱,则在检测到极小值和准确性损失二者时设置 UFL 标志(在这种情况下还设置 INX 标志);否则返回一个有正确符号的零。因为在结果被舍入之后检测下溢,在一些操作之后是否发生下溢依赖于舍入模式。
INX - inexact 不精确
如果操作的舍入的结果是不精确的(不同于可用无穷精度计算的值),或者在禁用 OFL 陷阱时发生上溢,或者在禁用 UFL 陷阱时发生了下溢,则设置 INX 标志。OFL 或 UFL 陷阱优先于 INX。在计算 SIN 或 COS 的时候也设置 INX 标志,但 SIN(0) 和 COS(1) 例外。老的 FPE 和 FPPC 系统在处理 INX 标志上可能不同。由于这个不一致性,我建议你不要启用 INX 陷阱。
精度:
S -
单精度 D -
双精度 E -
双扩展精度 P -
压缩(packed)十进制数 EP -
扩展压缩十进制数 舍入模式:
-
最近(不需要字符) P -
正无穷 M -
负无穷 Z -
零 LDF{条件}<精度>
装载浮点值。
地址可以是下列形式:
这个调用类似于 LDR。
你的汇编器可能允许使用如下文字:LDFS F0, [浮点值]
STF{条件}<精度>
存储浮点值。
地址可以是下列形式:
这个调用类似于 STR。
你的汇编器可能允许使用如下文字:STFED F0, [浮点值]
LFM
and SFM
它们类似于 LDM 和 STM,但因为一些版本的 FPEmulator 不支持它们就不进行描述了。最新版本的 RISC OS 3.1x (2.87) 中的 FP 模块支持。如果你想让你的软件只在支持 SFM 的系统上操作就使用它吧。否则你需要用 STF 的一个序列来‘伪造’它。LFM/LDF 也是类似。
FLT{条件}<精度>{舍入}
FLT{条件}<精度>{舍入}
转换整数成浮点数,要么从一个 ARM 寄存器要么从一个绝对值。
FIX{条件}{舍入} <寄存器>,
转换浮点数成整数。
WFS{条件} <寄存器>
用指定 ARM 寄存器的内容写浮点状态寄存器。
RFS{条件} <寄存器>
读浮点状态寄存器到指定的 ARM 寄存器中。
WFC{条件} <寄存器>
用指定 ARM 寄存器的内容写浮点控制寄存器。
专属超级用户模式,并只存在于支持它的硬件上。
RFC{条件} <寄存器>
读浮点控制寄存器到指定的 ARM 寄存器中。
专属超级用户模式,并只存在于支持它的硬件上。
浮点协处理器数据操作指令的格式是:
双目操作{条件}<精度>{舍入} <目的浮点寄存器>, <源浮点寄存器>, <源浮点寄存器> 双目操作{条件}<精度>{舍入} <目的浮点寄存器>, <源浮点寄存器>, #<值> 单目操作{条件}<精度>{舍入} <目的浮点寄存器>, <源浮点寄存器> 单目操作{条件}<精度>{舍入} <目的浮点寄存器>, #<值> <值>常量应当是 0、1、2、3、4、5、10、或 0.5。
双目操作有...ADF -
加法DVF -
除法FDV -
快速除法 - 只定义用单精度工作FML -
快速乘法 - 只定义用单精度工作FRD -
快速反向除法 - 只定义用单精度工作MUF -
乘法POL -
极化角POW -
幂RDF -
反向除法RMF -
余数RPW -
反向幂RSF -
反向减法SUF -
减法
单目操作有...ABS -
绝对值ACS -
反余弦ASN -
反正弦ATN -
反正切COS -
余弦EXP -
指数LOG -
常用对数LGN -
自然对数MVF -
传送MNF -
传送取负的值NRM -
规格化RND -
舍入到整数值SIN -
正弦SQT -
平方根TAN -
正切URD -
非规格化舍入
CMF{条件}<精度>{舍入}
把 FP 寄存器 2 与 FP 寄存器 1 进行比较。
变体 CMFE 比较带有例外。
CNF{条件}<精度>{舍入}
把 FP 寄存器 2 与 FP 寄存器 1 取负的值进行比较。
变体 CNFE 比较带有例外。
提供带例外和不带例外的比较,如果操作数是未对阶的(就是说它们中的一个或两个是非数)时可以引发这个例外。为了遵守 IEEE 754,CMF 指令只应用于测试等同(就是说以后使用 BEQ 或 BNE) 或测试未对阶(在 V 标志中)。应当对所有其他测试使用 CMFE 指令(以后用 BGT、BGE、BLT、BLE)。
当 FPSR 中的 AC 位清除了的时候,在比较之后,ARM 标志 N、Z、C、V 表示:N =
小于Z =
等于C =
大于等于V =
未对阶
当 FPSR 中的 AC 位设置了的时候,在比较之后,这些标志表示:N =
小于Z =
等于C =
大于等于或未对阶V =
未对阶
在使用 objasm 的 APCS 代码中,要存储一个浮点值,你可以使用宏指令(directive) DCF。对单精度添加‘S’,对双精度添加‘D’。