ARM 笔记

1. ARM

参考资料: ARM

1.1 内核种类

指令集架构处理器家族
ARMv1ARM1
ARMv2ARM2, ARM3
ARMv3ARM6、ARM7
ARMv4StrongARM、ARM7TDMI、ARM9TDMI
ARMv5ARM7EJ、ARM9E、ARM10E、XScale
ARMv6ARM11、ARM Cortex-M
ARMv7ARM Cortex-A、ARM Cortex-M、ARM Cortex-R
ARMv8Cortex-A35、Cortex-A50系列[18]、Cortex-A70系列、Cortex-X1
ARMv9Cortex-A510、Cortex-A710、Cortex-A715、Cortex-X2、Cortex-X3、ARM Neoverse N2

1.2 架构

  • "应用"配置: Cortex-A 系列
  • "嵌入式"配置: Cortex-R 系列
  • "微处理器"配置: ARM Cortex-M 系列。

1.3 CPU模式

1.3.1 模式分类

CPU ARM 架构指定了以下的CPU模式。在任何时刻,CPU只可处于某一种模式,但可由于外部事件(中断)或编程方式进行模式切换。

  1. USR-用户模式 [10000]
    唯一非特权模式,ARM处理器正常的程序执行状态
  2. FIQ-快速干预模式 [10001]
    处理器接受一条FRQ干预时进入的特权模式。用于高速数据传输或通道处理
  3. IRQ-外部中断模式[10010]
    处理器接受一条IRQ干预时进入的特权模式。用于通用的中断处理
  4. SVC-Supervisor 管理 模式 [10011]
    在CPU被重置或者SWI指令被执行时进入的特权模式,操作系统使用的保护模式
  5. ABT-Abort 模式 [10111]
    预读取中断或数据中断异常发生时进入的特权模式,当数据或指令预取终止时进入该模式,用于虚拟存储及存储保护
  6. UND-未定义模式 [11011]
    未定义指令异常发生时进入的特权模式。当未定义的指令执行时进入该模式,用于支持硬件协处理器的软件仿真
  7. SYS系统模式 [11111]
    仅无需例外进入的特权模式。仅以执行明确写入CPSR的模式位的指令进入,运行具有特权模式的操作系统任务
  8. Hyp 模式
    armv-7a为cortex-A15处理器提供硬件虚拟化引进的管理模式。
权限Modeuserprivilegedprivilegedprivilegedprivilegedprivilegedprivileged
寄存器Modeusersystemexceptionexceptionexceptionexceptionexception
类型Modeusrsyssvcabtundirqfiq
ValueBit10000111111001110111110111001010001
ValueHex0x100x1F0x130x170x1B0x120x11

1.3.2 System Mode

参考 System Mode
5.12. System mode
The ARM Architecture defines a User mode that has 15 general purpose registers, a pc, and a CPSR. In addition to this mode there are five privileged processor modes, each of which have an SPSR and a number of registers that replace some of the 15 User mode general purpose registers. Note This section only applies to processors that implement ARM architectures v4, v4T and later.
When a processor exception occurs, the current program counter(PC) is copied into the link register(LR) for the exception mode, and the CPSR is copied into the SPSR(SPSR_Exception)for the exception mode. The CPSR is then altered in an exception-dependent way, and the program counter(PC) is set to an exception-defined address to start the exception handler. The ARM subroutine call instruction (BL) copies the return address into r14 before changing the program counter(PC), so the subroutine return instruction moves r14 to pc (MOV pc,lr).
Together these actions imply that ARM modes that handle exceptions must ensure that another exception of the same type cannot occur if they call subroutines, because the subroutine return address will be overwritten with the exception return address.(In earlier versions of the ARM architecture, this problem has been solved by either carefully avoiding subroutine calls in exception code, or changing from the privileged mode to User mode.The first solution is often too restrictive, and the second means the task may not have the privileged access it needs to run correctly.) ARM architecture v4 and later provide a processor mode called system mode, to overcome this problem. System mode is a privileged processor mode that shares the User mode registers. Privileged mode tasks can run in this mode, and exceptions no longer overwrite the link register.
Note:
System mode cannot be entered by an exception. The exception handlers modify the CPSR to enter System mode. See Reentrant interrupt handlers for an example.
大体意思如下:
当处理器异常出现时,当前程序计数器(也就是 PC+offset,offset与异常种类相关)会被拷贝的相应异常模式的 LR,CPSR 也会被拷贝到相应异常模式的 SPSR。然后 CPSR 会被设置为相应的异常模式, PC 被设置到对应异常的入口处执行其处理函数。(上面这些都是ARM核自动操作的)
ARM的子程序转移指令BL会在改变PC前将返回地址放到LR中,所以从子程序返回时可以把r14放到PC来操作。如 MOV pc, lr。
所有上面的动作都暗示了如果异常处理函数会调用子程序(使用 BL),那么各异常模式都必须保证异常处理函数执行的过程中不能出现同样的异常,因为子函数的返回地址会被异常的返回地址覆盖掉。(在早期的ARM版本 中,可以通过禁止异常处理函数调用子函数或者切换处理模式到User模式来解决这个问题。第一种方式过于严格,而第二种方式可以会由于User模式缺少相 应的权限而不能执行某些动作)。
为此,ARM v4及之后的版本提供了system mode这样一种处理器模式来解决这个问题。System mode是一种privileged的模式,而且共用User模式的所有寄存器。Privileged模式的程序可以运行在这个模式,而不用担心处理器异常会覆盖 LR。
注意:
System mode不是因为发生了某种异常处理器自动进入的模式,而是异常处理函数通过修改CPSR来进入的。

1.4 指令集

大多数ARM处理器支持超过一种指令集:

  1. ARM— 一种32位指令集
  2. Thumb— 一种16位指令集,具有更好的代码密度(但是相比ARM代码,性能有所降低) 在程序的控制之下,处理器可以在这两种指令集之间来回切换。
  3. Thumb-2-- 所有的Cortex-A系列处理器实现了Thumb-2技术,它扩展了Thumb指令集。混合使用32位和16位指令,以Thumb指令集的代码密度和接近ARM指令集的性能。自从所有的Cortex-A系列处理器支持这一扩展,针对它们的软件常被编译成Thumb指令集。(本文作者注:按照文章《如何使用Thumb-2改善代码密度和性能》所述,Thumb-2代码大小约为ARM代码的74%,性能则为其98%)

1.5 寄存器

ARM V7寄存器

1.5.1 寄存器分组

ARM处理器含有37个寄存器,这些寄存器包括以下两类寄存器。
(1)31个通用寄存器:包括程序计数器PC等,这些寄存器都是32位寄存器。
(2)6个状态寄存器:状态寄存器也是32位的寄存器,但是只使用了其中的12位。
(3)NEON寄存器是Q0~Q15共计16个。

在ARM处理器的7种模式下都有一组对应的寄存器组。在任意时刻,可见的寄存器组包括15个通用寄存器R0~R14、1 个或2个状态寄存器和PC。在所有的寄存器中,有些是各种模式下共用的同一个物理寄存器,有些是各种模式自己独立拥有的物理寄存器。
寄存器 R0-R7 对于所有CPU模式都是相同的,它们不会被分块。
对于所有的特权CPU模式,除了系统CPU模式之外,R13和R14都是分块的。也就是说,每个因为一个异常(exception)而可以进入的模式(Mode)都有其自己的R13和R14。这些寄存器通常分别包含堆栈指针和函数调用的返回地址。

同名的名称:

  • R13 也被指为 SP(Stack Pointer)
  • R14 也被指为 LR(Link Register)
  • R15 也被指为 PC(Program Counter)

通用寄存器通常又可以分为下面3类:

  1. 未备份寄存器:包括R0~R7;
  2. 备份寄存器:包括R8~R14;
  3. 程序计数器PC:即R15。
    对于每个未备份寄存器来说,在所有的处理器模式下指的都是同一个物理寄存器,在异常中断造成处理器模式切换时,由于不同的处理器模式使用相同的物理寄存器,可能造成寄存器中数据被破坏。未备份寄存器没有被系统用于特别的用途,任何可采用通用寄存器的应用场合都可以使用未备份寄存器。

1.5.2 R0 - R12

用来在通用操作中存储临时的值,指针等。

  • R0 被用来存储函数调用的返回值。
  • R7 经常被用作存储系统调用号。
  • R11 存放着帮助我们找到栈帧边界的指针。
  • 在ARM的函数调用约定中,前四个参数按顺序存放在R0-R3中。

1.5.3 备份寄存器R8~R14

备份寄存器中的每个寄存器对应于两个不同的物理寄存器。例如,当使用快速中断模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_fiq和 R9_fiq,当使用用户模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_usr和R9_usr等。
在这两种情况下使用的是不同的物理寄存器,系统没有将这几个寄存器用于任何的特殊用途。中断处理非常简单,仅仅使用R8~R14寄存器时,FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程很迅速。
对于备份寄存器R13、R14来说,每个寄存器对应于6个不同的物理寄存器,其中的一个是用户模式和系统模式共用的, 另外的5个则对应于其他5种处理器模式

1.5.4 FP (R11)

FP: (Frame Pointer)初始化帧指针寄存器 ,fp为帧寄存器,起 “标签” 作用。
每一种体系结构都有这么个一个东西,当调用一个c函数,必须有一个寄存器来指明局部变量区域的位置,函数推出后堆栈的位置和上一层的局部变量的区域。
这个其实是编译系统中活动记录的东西。
c 函数会使用堆栈,故而会使用sp寄存器, 但函数执行完后要恢复sp寄存器,通常会保留原来的寄存器,我们把它叫old-sp寄存器。
arm 用fp寄存器充当这个角色。
'frame pointer 在函数生命期内其值是不变的。
局部变量是保存在堆栈中的,函数退出即丢弃。'通过frame pointer 可以获得局部变量的地址。

1.5.5 IP (R12)

内部过程调用寄存器
它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。
在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 R12。

1.5.6 SP (R13)

R13_<mode>,其中<mode>是usr、svc、abt、und、irq和fiq的一种。
R13通常用做堆栈指针<"SP">。每一种模式都拥有自己的物理R13。程序初始化R13,使其指向该模式专用的栈地址。
当进入该模式时,可以将需要使用的寄存器保存在R13所指的栈中,当退出该模式时,将保存在R13所指的栈中的寄存器值弹出。这样就实现了程序的现场保护。
R13:SP(栈指针)。栈指针寄存器用来指向当前的栈顶。栈是一片来存储函数调用中相关数据的内存,在函数返回时会被修改为对应的栈指针。
栈指针用来帮助在栈上申请数据空间。比如说你要申请一个字的大小,就会将栈指针减4,再将数据放入之前所指向的位置。
用户模式和系统模式共用一个SP,每种异常模式都有各自专用的R13寄存器(SP)。它们通常指向各模式所对应的专
用堆栈,也就是ARM处理器允许用户程序有六个不同的堆栈空间

1.5.7 LR (R14)

寄存器R14又被称为链接寄存器(“LR”),在ARM中有下面两种特殊用途。
① 每一种处理器模式在自己的物理R14中存放当前子程序的返回地址。当通过BL或者BLX指令调用子程序时,R14被设置成该子程序的返回地址。在子程序中,当把R14的值复制到程序计数器PC中时,就实现了子程序返回。
可以通过下面两种方式实现这种子程序的返回操作。

    # 方式1
    mov pc, lr
    # 方式 2 
    bx    lr

在子程序入口使用下面指令将PC保存到栈中:

STMFD  SP!, {registers}, LR}

相应地,下面的指令可以实现子程序的返回:

LDMFD  SP!, { registers}, LR }

② 当发生异常中断的时候,该模式下的特定物理R14被设置成该异常模式将要返回的地址。对于某些异常,R14的值可能与将返回的地址有一个常数的偏移量。具体的返回方式与上面的子程序返回方式基本相同。
在ARM处理器中使用 R14实现对断点和调用点的记录,即使用R14用作返回链接寄存器(LR)。在硬件上和指令执行上,CPU 自动完成相应返回点的记录。
在ARM 汇编语言程序设计时,R14 和 LR 通用。
ARM处理器相应异常时,会自动完成将当前的PC保存到 LR 寄存器。
ARM处理器执行子程序调用指令(BL )时,会自动完成将(当前的 PC - 4)的值保存到LR寄存器。即将调用指令的下一个紧邻指令的地址保存到 LR。
ARM处理器针对不同的模式,共有6个链接寄存器资源(LR ),其中用户模式和系统模式共用一个 LR,每种异常模式都有各自专用的R14 寄存器(LR )。这些链接寄存器分别为 R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq,
程序设计者要清晰处理器的模式与相应寄存器的对应关系,都是使用 R14,但不同模式下的 R14 不是同一个物理资源,其内容可能天壤之别。
R14 不用做链接寄存器(LR )时,也可以用做通用数据寄存器。
R14:LR(链接寄存器)。
当一个函数调用发生,链接寄存器就被用来记录函数调用发生所在位置的下一条指令的地址。这么做允许我们快速的从子函数返回到父函数。

在ARM体系结构中LR的特殊用途有两种:

  1. 执行子程序调用指令(BL )时,会自动完成将当前的PC的值减去4的结果数据保存到LR寄存器。即将调用指令的下紧邻指令的地址保存到LR。返回时将 LR 赋给 PC即可;
  2. 当异常发生时,会自动完成将当前的PC保存到LR寄存器,返回时将 (LR - 4)赋给 PC 即可,因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。

为什么异常发生时,需要 sub lr, lr, #4 ?
是因为arm流水线,也就是执行第1条指令,第2条指令进行译码,将第3条指令从存储器中取出,那么pc当前等于pc+8,所以在异常发生时,此时 LR = PC + 8,但是 (PC+4) 是没有被执行的,所以异常返回时需要返回到 (LR-4) 地址上,执行已经译码的地址上.

1.5.8 PC (R15)

R15 程序计数器PC→R15

程序计数器R15又被记作<“PC”>。它虽然可以作为一般的通用寄存器使用,但是有一些指令在使用R15时有一些特殊限制。当违反了这些限制时,该指令执行的结果将是不可预料的。
由于ARM采用了流水线机制,当正确读取了PC的值时,该值为当前指令地址值加8个字节。 也就是说,对于ARM指令集来说,PC指向当前指令的下两条指令的地址。由于ARM指令是字对齐的,PC值的第0位和第1位总为0。
需要注意的是,当使用指令STR/STM保存R15时,保存的可能是当前指令地址值加8字节,也可能保存的是当前指令地址加12字节。
到底是哪种方式,取决于芯片具体设计方式。无论如何,在同一芯片中,要么采用当前指令地址加8,要么采用当前指令地址加12,不能有些指令采用当前指令地址加8,另一些指令采用当前指令地址加12。因此对于用户来说,尽量避免使用STR/STM指令来保存R15的值。当不可避免这种使用方式时,可以先通过一些代码来确定所用的芯片使用的是哪种实现方式。
假设R0指向可用的一个内存字,下面代码可以在R0指向的内存字中返回该芯片所采用的地址偏移量。

sub        r1, pc, #4            @ R1中存放下面STR指令的地址
str        pc, [r0]              @ 将PC=STR地址+offset保存到R0中
ldr        r0, [r0]              @
sub        r0, r0, r1            @ offset=PC-STR地址

PC 代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:

  1. 取指(从存储器装载一条指令);
  2. 译码(识别将要被执行的指令);
  3. 执行(处理 指令并将结果写回寄存器)。

而R15(PC)总是指向"正在取指"的指令,而不是指向"正在执行"的指令或正在"译码"的指令。
一般来说,人们习惯性约定 将"正在执行的指令作为参考点",称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8;
ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4 假设在ARM状态 下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
当突然发生中断的时候,保存的是PC的地址。
这样你就知道了,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用

SUB pc lr-irq #4

注意pc,在调试的时候显示的是当前指令地址,而用 mov lr,pc 的时候 LR 保存的是此指令向后数两条指令的地址,大家可以试一下用 mov pc,pc,结果得到的是跳转两条指令,这个原因是由于arm的流水线造成的,预取两条指令的结果.

如何访问常量数据
当前pc值加存放数据地址就是真实数据地址

1.6 Exception

1.6.1 Exception & Mode & Priority

1.6.2 Vector Table

the vector table—a table of addresses that the ARM core branches to when an exception is raised. These addresses commonly contain branch instructions of one of the following forms:

  • B
    —This branch instruction provides a branch relative from the pc.
  • LDR pc, [pc, #offset]—This load register instruction loads the handler address from memory to the pc. The address is an absolute 32-bit value stored close to the vector table. Loading this absolute literal value results in a slight delay in branching to a specific handler due to the extra memory access. However, you can branch to any address in memory.
  • LDR pc, [pc, #-0xff0]—This load register instruction loads a specific interrupt serviceroutine address from address 0xfffff030 to the pc. This specific instruction is only used when a vector interrupt controller is present (VIC PL190).
  • MOV pc, #immediate—This move instruction copies an immediate value into the pc. It lets you span the full address space but at limited alignment. The address must be an 8-bit immediate rotated right by an even number of bits.

还可以在向量表中包含其他类型的指令。 例如,FIQ Handler 可能从地址偏移 +0x1c 开始。 因此,FIQ Handler 可以立即从 FIQ 向量位置开始,因为它位于向量表的末尾。 分支指令使 pc 跳转到可以处理特定异常的特定位置。
表 9.2 显示了每个异常的异常、模式和向量表偏移量。

Figure 9.2 shows a typical vector table. The Undefined Instruction entry is a branch instruction to jump to the undefined handler. The other vectors use an indirect address jump with the LDR load to pc instruction.
Notice that the FIQ handler also uses the LDR load to pc instruction and does not take advantage of the fact that the handler can be placed at the FIQ vector entry location.

1.6.3 Exception Priority

当 Exception 同时发生的时候,需要按照优先级机制处理,优先级设置如下图。
Priority 数字越小,优先级越高。
Exception 发生的同时会 disable Interrupt ,即将 CPSR 中的 I bit 或 F bit 置为1,
比如,当CPU上电的时候,最先发生 Reset Exception。

按照优先级顺序,处理 Exception的总结:

1.6.3.1 Reset Exception

Reset Exception 的优先级最高,总是在发出信号时被处理。Reset Handler 会初始化系统,包括设置内存和缓存。外部中断源应在使能 IRQ 或 FIQ 中断之前初始化,以避免在设置适当的Handler之前发生虚假中断的情况。 复位处理程序还必须为所有处理器模式设置堆栈指针。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值