ARM寄存器集
列出了ARM的16个程序员可见寄存器(r0~r15)以及它的状态寄存器。
ARM共有14个通用寄存器r0~r13。寄存器r13被保留用作栈指针,r14存放子程
序返回地址,r15为程序计数器。
由于r15能够被程序员访问,因此能够执行可以计算的分支(如高级语言case语
句中所用的操作类型)。ARM的16个寄存器需要4位地址,相对于32个寄存器
(5位地址)的RISC处理器来说,每条指令可以节约3位。这种方法使得ARM的
指令比一些RISC处理器丰富得多。
寄存器r13被保留用作栈指针。与特殊功能寄存器r14和r15不同,它们的附加功
能由ARM硬件实现,仅当程序员需要r13作为栈指针时它才会成为栈指针。
ARM的当前处理器状态寄存器CPSR包括Z(零)、N(负)、C(进位)和V(溢
出)等标志位,类似于其他处理器中的条件码或状态寄存器。CPSR的低8位包
含系统信息
ARM指令集
指令集分类方法:数据移动、算数运算、逻辑运算、移位、程序控制
更新ARM条件码
与绝大多数CISC体系结构不同,ARM不会在算数和逻辑运算后自动更新状态标志。ARM提供按需更新模式,仅仅在当前指令借记符带有后缀s时候才会自动更新条件码。
如,指令ADD r1,r2,r3进行加法操作,不更新状态标志,而指令ADDS r1,r2,r3则
会更新状态标志。
- SUBS r1,r1,#1 ; r1减1并设置状态位
- ADD r2,r2,#4 ; 计数器递增,不更新状态位
- MUL r5,r3,r4 ; r3与r4相乘,不更新状态位
- BEQ Error ; 如r1为0则跳转去处理问题
ARM汇编语言
Test_5
ADD r0,r1,r2 ; 计算TotalTime =Time +NewTime
SUBS r7,#1 ; 循环计数器递减
BEQ Test_5 ; 为0则跳转到Test_5处
例2
计算数字1~10的立方和,可以使用乘累加指令实现
MOV r0,#0 ; r0 = 0
MOV r1,#10 ; FOR i = 1 to 10(向下计数)
Next MUL r2,r1,r1 ; 计算平方
MLA r0,r2,r1,r0 ; 计算立方并累加
SUBS r1,r1,#1 ; 计数器递减(设置标志位)
BNE Next ; END FOR(计数值不为零时跳转)
汇编程序由两部分组成:计算机可执行指令和告诉汇编器运行环境有关信息的
汇编伪指令。汇编伪指令告诉汇编器代码在存储器中的位置,为变量分配存储
空间,以及设置程序运行时所需的初始数据。
ARM程序结构
下述代码描述了一个简单的程序结构,计算整数1~10立方和的程序,加阴影的
文字表示汇编伪指令而不是可执行的ARM代码:
汇编伪指令AREA定义代码段
段的名字为ARMTest,属性为CODE和READONLY
汇编伪指令ENTRY告诉汇编器在哪里找到要执行的第一条指令
伪指令END是强制的,告诉汇编器已经到达程序末尾
伪指令
伪指令是程序员可用的指令,但不是处理器ISA的一部分,伪指令是一种速记形式,程序员可用用它简单的表示一个动作,并使汇编器生成合适的代码。
CISC处理器能将地址以及16位或32位数据加载到寄存器中。由于ARM是规整的32位指令格式,不能直接实现这样的指令。
如,想把32位十六进制数0x1234567加载到寄存器r0中,不能写成MOV r0,#0x1234567(why?)。ARM汇编器提供了能够简化常量加载的方法。
伪指令ADR
伪指令ADR,把地址加载到目的寄存器中。该指令格式为ADR rdestination label,
label是程序中有效地址标号。尽管我们会在程序中看到ADR,但它并不是一个
真正的指令,因为没有指令能把32位常量加载到ARM寄存器中。ADR是一个可
由程序员使用的伪操作或虚拟指令,之后汇编器将生成完成同样功能的实际机
器代码。
伪指令是一种便捷的形式,汇编器将其转换为实际指令,将程序员从一些事务
性的工作解脱出来。一般来说,ADR能够利用ARM的ADD或SUB指令以及PC相对
寻址方式产生所需要的地址。
下面代码说明ADR的使用方法:
ADR r1,MyArray ; 使r1指向MyArray
LDR r3,[r1] ;
MyArray DCD 0x12345678 ;用指针读出一个元素
编译器会生成将已知值载入寄存器rd中的代码,如
LDR r0, = 0x12345678
把数据1234567816加载到寄存器r0中。汇编器会使用指令MOV或MVN,或使用一条LDR r0,[PC,#offset]指令去访问常数1234567816,该常数被存放在位于存储器中某处的立即数池或常数池。
ARM是如何处理伪指令的,考虑以下代码段(虚拟代码,仅用于说明伪指令用法): AREA ConstPool, CODE, READONLY
ENTRY
LDR r0,=0x12345678 ; 将32位常量加载到r0中
ADR r1,Table ; 将Table的地址加载到r1中
ADR r2,Tabel1 ; 将Table1的地址加载到r2中
LDR r3,=0xAAAAAAAA ; 将32位常量加载到r3中
LDR r4,P3 ; 这条语句的功能是什么?
Table DCD 0xABCDDCBA ; 虚拟数据
Table1 DCD 0xFFFFFFFF ;
P3 DCD 0x22222222 ;
地址 数据/指令 说明
0x00000000 LDR r0, [PC, #0x10] 加载 0x12345678
0x00000004 ADD r1, PC, #0x0C 计算 Table 地址
0x00000008 ADD r2, PC, #0x08 计算 Table1 地址
0x0000000C LDR r3, [PC, #0x0C] 加载 0xAAAAAAAA
0x00000010 LDR r4, [PC, #0x0C] 加载 P3 处的数据
0x00000014 0x12345678 文字池:LDR r0 的常量
0x00000018 0xAAAAAAAA 文字池:LDR r3 的常量
0x0000001C 0xABCDDCBA Table 数据
0x00000020 0xFFFFFFFF Table1 数据
0x00000024 0x22222222 P3 数据