ARM指令系统与编程
2inc

CPU 识别并执行的指令是由0、1二进制数组成的一串二进制码。可以让计算机执行某种操作的命令,称为机器指令。计算机的指令系统是指该计算机的 CPU 所能识别和执行的全部指令的集合。ARM 微处理器的低功耗、高性能特性主要归功于其高效的指令集架构 ISA。本章重点讲述 ARMv7架构的指令系统,包括 ARM 指令的指令格式、条件码、ARM 指令的寻址方式和 ARMv7架构下的 Thumb–2指令集。

3.1 ARM 指令系统简介

image

ARM 开发工具中新支持的统一汇编语言 UAL(unified assembly language)统一了 ARM 指令集和 Thumb 指令

3.1.2 指令格式

指令的格式由表示操作性质的操作码和表示操作对象的操作数两部分组成。
指令基本格式及示例

1
2
3
<opcode>{<cond>}{S} <Rd>,<Rn>{,<shifter_operand>}
MOVS R1, R2 ;
MOV R1, R2 ;

image
条件码(cond)
image

第二源操作数(shifter_operand)

  1. 立即数方式( #immend
    对于 32 位 ARM 指令,留给第二操作数立即数的只有 12 位,为了利用这 12 位来表示一个 32 位的立即数,可以将该立即数的空间分为两段:一段为 8 位的立即数(immend_8) 另一端 4 位为循环移位的位数(rotate_imm)
    32 位立即数=immend_8 循环右移(2*rotate_imm 位)
    (为避免数据在首尾被分开,具体编码规则如下表)
    image
  2. 寄存器方式
  3. 寄存器移位方式

3.2 ARM 指令的寻址方式

3.2.1 立即寻址

操作数直接放在指令中,例如
image

3.2.2 寄存器直接寻址

是各类寄存器中通常采用的一种执行效率较高的寻址方式
image

3.2.3 寄存器一位寻址

1
AND    R0,    R1,    R2,    LSL#2    ;

3.2.4 寄存器间接寻址

寄存器中存放的内容是操作数的内存地址,用中括号括起来
image

3.2.4 基址变址寻址

某个寄存器提供一个基准地址,通过将该基准地址与指令中给出的“地址偏移量”相加,形成有效地址
image

3.2.6 多寄存器直接寻址

LDM(加载多个寄存器)和 STM(存储多个寄存器),实现一个指令完成多个通用寄存器的传送
image

3.2.7 堆栈寻址

3.3 ARM 核心指令

3.3.1 数据传送指令

  1. 寄存器间传送数据
  2. 寄存器合特殊功能寄存器传送数据
  3. 把一个立即数加在到寄存器
    核心:MOV
    image

3.3.2 存储器访问指令

1. 单寄存器加载和存储指令

2. 自动索引

3. 前索引

1
LDR R0,    [R1,#20]!    ;

步骤 1:R0<- [ R1+20 ]
步骤 2:R1=R1+20sd

4. 后索引

3.3.3 算术运算

  1. ADD R16, R17, R18: 将寄存器R17和R18中的值相加,并将结果存储在R16中。
  2. SUB R19, R20, #3: 从寄存器R20中减去立即数3,并将结果存储在R19中。
  3. MUL R21, R22, R23: 将寄存器R22和R23中的值相乘,并将结果存储在R21中。
  4. SDIV R24, R25, R26: 将寄存器R25中的值除以R26中的值,并将结果存储在R24中。
  5. RSB R27, R28, #7: 将立即数7减去寄存器R28中的值,并将结果存储在R27中。

3.3.4 逻辑运算

  1. AND R29, R30, #0x0F: 对寄存器R30的值和0x0F进行逻辑与操作,并将结果存储在R29中。
  2. EOR R31, R32, #0x55: 对寄存器R32的值和0x55进行异或操作,并将结果存储在R31中。
  3. BIC R33, R34, #0x80: 对寄存器R34的值和0x80进行位清零操作,并将结果存储在R33中。
  4. ORR R35, R36, R37: 对寄存器R36和R37中的值进行逻辑或操作,并将结果存储在R35中。
  5. MVN R38, R39: 对寄存器R39的值进行按位取反操作,并将结果存储在R38中。

3.3.5 移位和循环指令

  1. ROR R40, R41, #1: 将寄存器R41的值向右旋转1位,并将结果存储在R40中。
  2. RRX R42, R43: 将寄存器R43的值右移1位,同时将旧的标志位放入R42。
  3. LSL R44, R45, R46: 将寄存器R45的值左移R46中的位数,并将结果存储在R44中。
  4. ASR R47, R48, R49: 对寄存器R48的值进行算术右移R49中的位数,并将结果存储在R47中。

3.3.6 符号扩展

  1. SXTH R50, R51: 将寄存器R51中的16位半字符号扩展为32位,并将结果存储在R50中。
  2. SXTB R52, R53: 将寄存器R53中的8位字节符号扩展为32位,并将结果存储在R52中。
  3. UXTB R54, R55: 将寄存器R55中的8位无符号字节扩展为32位,并将结果存储在R54中。

3.3.7 字节调序

  1. REV R56, R57: 反转寄存器R57中的字节顺序,并将结果存储在R56中。
  2. REV16 R58, R59: 反转寄存器R59中的16位数据的顺序,并将结果存储在R58中。
  3. REVSH R60, R61: 反转寄存器R61中的16位数据的顺序,同时进行符号扩展,并将结果存储在R60中。

3.3.8 位域处理

  1. BFI R62, R63, #3, #5: 将寄存器R63中的5位数据插入到寄存器R62的位域中,从第3位开始。
  2. BFC R64, #8, #4: 将寄存器R64的位域从第8位开始清零,清零的位数为4。

3.3.9 子程序调整和无条件转移

  1. BL Label1: 无条件分支到一个标签(子程序Label1),并将返回地址存储在链接寄存器中,用于后续的返回。
  2. BX LR: 通过链接寄存器返回到子程序调用的地址。>)

4.1 汇编语言程序

4.1.1 格式

1
2
3
4
N EQU 10   ; 定义常量N10
Stack_Size EQU 0x00000400; 定义栈空间大小
AREA MyStack, NOINIT, READWRITE, ALIGN=3; 声明栈段
Stack_Mem SPACE Stack_Size ;分配内存空间

image

常用的汇编指示命令

数据常量定义

1
名称 EQU 表达式{,类型}

数据常量定义

1
2
3
4
5
6
7
8
9
GBLA Test1 ; 定义一个全局数字变量,初始化0
GBLL Test2 ; 定义一个全局逻辑变量,初始化F
GBLS Test3 ; 定义全局字符串变量

LCLA(L/S) Test4 ; 定义局部变量

SETA(L/S) Test5 ; 重新赋值已定义的变量

RegList RLIST {R0-R5,R8,R10} ; 将寄存器列表名称定义为RegList

内存分配

image
image

汇编控制汇编指示命令

1
2
3
4
5
IF 逻辑表达式
指令序列1
ELSE
指令序列2
ENDIF
1
2
3
WHILE 逻辑表达式
指令序列
WEND

其他常用汇编指令

image

 评论
评论插件加载失败
正在加载评论插件