ARM 汇编指令集
- Android 平台的 ARM 汇编指令集根据架构支持类型的不同可分为四大类:
- 注意:
- ARM 指令集一直在变化,armeabi 支持 ARMv7 以下版本的指令集,armeabi-v7a 支持 ARMv7 系列指令集,AArch32 支持的 ARM 指令集兼容之前的版本
- 编译器支持方面:Clang 只能通过
-target
参数指定 EABI 版本,不能指定具体的arch
参数;而 gcc 支持用-arch
参数指定具体的指令集,包括 ARMv2、ARMv2A、ARMv3、ARMv3M、ARMv4、ARMv4T、ARMv5、ARMv5E、ARMv5T、ARMv5TE、ARMv6、ARMv6-M、ARMv6J、ARMv6K、ARMv6T2、ARMv6Z、ARMv6ZK、ARMv7、ARMv7-A、ARMv7-M、ARMv7-R、ARMv7e-M、ARMv7VE、ARMv8-A、ARMv8-A+crc、iWMMXT、iWMMXT2、Native。在 Android 系统不同的 EABI 设置下,ARMv5TE、ARMv7-A、ARMv8-A 是编译器默认的选择
ARM 指令集分类
- armeabi-v8a 的 AArch32 与 armeabi-v7a 支持所有的 ARM 指令集,按指令的位域和功能可分为这几种:
- Data-processing and miscellaneous instructions:数据处理与杂项指令
- Load/store word and unsigned byte:加载存储指令
- Media instructions:媒体指令
- Branch, branch with link, and block data transfer:分支、带链接的分支与块数据传输指令
- Supervisor Call and coprocessor instructions:软中断与协处理器指令
- unconditionally executed instructions:无条件执行指令
ARM 指令编码
- ARM 指令集采用 32 位的等长编码格式,按类型的位域分布:
- 采用位域方式对一条 ARM 指令进行划分,最基本的域有 cond、op1、op。这三个域的取值会直接影响指令的具体类别与格式。cond 域占用 28 位到 31 位,共四位,记为
bits[31:28]
,每个位记录了一个条件标志(Conditon Flag)。这四个标志位具体如下:- N:
bit[31]
,负数标志 - Z:
bit[30]
,0 标志 - C:
bit[29]
,进位标志 - V:
bit[28]
,溢出标志
- N:
- 每条 ARM 指令的
bits[31:28]
中都有条件标志,若相应的标志位为 1,表示这条指令会影响标志位的结果。指令执行后,可通过查看 APSR 寄存器的 cond 域来查看标志。在应用级别,APSR 对应 CPSR,代表了程序状态寄存器;在系统级别,APSR 对应 SPSR。在 Android 原生 ARM 程序中,我们通常只能访问 CPSR - 不同的标志位组合在一起,可表示不同的含义:
cond | 助记符 | 含义(整型) | 含义(浮点型) | 条件标志 |
---|---|---|---|---|
0000 | EQ | 相等 | 相等 | Z == 1 |
0001 | NE | 不等 | 不等或无序 | Z == 0 |
0010 | CS | 进位 | 大于等于或无序 | C == 1 |
0011 | CC | 进位清除 | 小于 | C == 0 |
0100 | MI | 减、负数 | 小于 | N == 1 |
0101 | PL | 加、正数或 0 | 大于等于或无序 | N == 0 |
0110 | VS | 溢出 | 无序 | V == 1 |
0111 | VC | 未溢出 | 有序 | V == 0 |
1000 | HI | 无符号大于 | 大于或无序 | C == 1 and Z == 0 |
1001 | LS | 无符号小于或等于 | 小于或等于 | C == 0 or Z == 1 |
1010 | GE | 有符号大于或等于 | 大于或等于 | N = |