欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ARM汇编程序设计学习笔记(一)

程序员文章站 2022-06-09 08:27:49
...

ARM汇编程序设计学习笔记(一)

为了学习android系统,发现需要学习linux驱动,发现学习linux驱动,需要先知道处理器的各种架构,为了学习此种知识,发现网上有很多mini2440相关的知识,因此,将其作为蓝本,认真学习。直到linux驱动的学习完成。

这是linux驱动学习的第一部分,arm的汇编程序。

本文档的大部分资料翻译于《S3C2440A 32-BIT CMOS MICROCONTROLLER USER’S MANUAL》

一.编程模型

处理器工作状态

从程序员的角度来看,ARM920T(s3c2440的内核)有如下两种状态:

  1. ARM状态,执行32位,字对齐的指令
  2. THUMB状态,执行16位,半字对齐的THUMB指令。

注意:这两种状态的切换,不会影响处理器的模式和寄存器状态

1.1 切换状态

进入THUMB状态

将操作数寄存器的第0位,设为1,然后执行BX指令,就可以切换为THUMB状态。

例如:

BX Rm;如果Rm的第0位,是1,则跳转到Rm所在的地址,并且设置处理器在thumb模式下

如果在THUMB状态下,进入了异常,从异常中退出,依然是THUMB状态

进入ARM状态

可以通过下面的方法,进入arm状态:

  1. 将操作数寄存器的第0位,清零,然后执行BX指令
BX Rm;如果Rm的第0位,是0,则跳转到Rm所在的地址,并且设置处理器为arm模式下
  1. 处理器发生异常时,PC被放置在异常模式下的连接寄存器中,然后从异常向量地址开始执行

1.2 内存格式

ARM920T 将内存视为一个线性的字节序列。字节地址从0开始。0到3字节保存第一个字。4到7字节保存第二个字,依次类推。这些字支持小端和大端格式。

1.3 指令长度

指令长度为32位长(arm模式)和16位长(thumb模式)

1.4 数据类型

ARM920T 支持字节(8位)、半字(16位)、字(32位)数据类型。字必须4字节对齐。半字必须两字节对齐。

1.5 运行模式

ARM920T 支持7种运行模式:

  1. User(usr):最普通的arm执行状态
  2. FIQ(fiq):被用来进行数据传输,和信道处理
  3. IRQ(irq):通用的中断处理
  4. Supervisor(svc):为操作系统设计的保护模式
  5. Abort mode(abt):数据和指令预取发生问题时,进入
  6. System(sys):为操作系统设计的特权用户模式
  7. Undefined(und):当一个未定义的指令执行时,进入此模式

模式的改变可以通过软件控制,也可以通过外部的中断,或者异常。大多数的应用程序将运行在用户模式下。

特殊模式(非用户模式)仅仅在服务中断或者异常,或者访问受保护的资源时才会进入。

1.6 寄存器

ARM920T 总共有37个寄存器。其中,31个通用的32位寄存器和6个状态寄存器。这37个寄存器,对于程序来说,不能同时可见。

处理器状态和运行模式,决定了那些寄存器对于程序员来说可见。

1.7 arm状态下的寄存器集

在arm状态下,程序员只能看到16个通用寄存器和1个或者2个状态寄存器。在特殊模式(非用户模式),相应的寄存器组被切换。图2-3展示了在每种模式下那些寄存器可见。这些寄存器组使用一个阴影三角形标记:

ARM汇编程序设计学习笔记(一)

arm状态下的寄存器组包含16个可直接访问的寄存器:R0-R15.除了R15寄存器以外,其他的寄存器都是通用寄存器。可以用来存储数据或者地址。

除此之外,还有第十七个寄存器用来存储状态信息。

寄存器 描述
寄存器14 该寄存器作为子程序的链接寄存器。当分支指令(Branch)和连接指令(BL)执行时,这个寄存器保存R15的值.其他时候,可以被作为通用寄存器来使用。对应的寄存器有:R14_svc,R14_irq,R14_fiq,R14_abt,R14_und,他们都在对应的模式下保存R15的值
寄存器15 这个寄存器为程序计数器(PC)。在arm模式下,bits[1:0]是0,bits[31-2]保存PC。在thumb模式下,bit[0]为0,bits[31:1]保存PC
寄存器16 这个寄存器是CPSR(当前程序状态寄存器)。它保存代码的各种flag和一些模式位

FIQ模式有7个寄存器,被映射为R8-R14(R8_fiq-R14_fiq).在arm模式下有许多FIQ处理程序不需要保存的寄存器。

而USer,IRQ,SuperVisor,Abort和Undefined模式,都有R13和R14,并且允许他们有自己的堆栈指针和链接寄存器

ARM和THUMB之间的寄存器关系

如下:

  1. THUMB模式下R0-R7 ,ARM模式下R0-R7 完全相同
  2. THUMB模式下CPSR和SPSRs,ARM模式下CPSR和SPSRs是完全相同的
  3. THUMB模式下SP映射为ARM的R13
  4. THUMB模式下LR映射为ARM下的R14
  5. THUMB模式下PC映射为ARM的R15

ARM汇编程序设计学习笔记(一)

在thumb模式下访问高寄存器组(Hi-registers)

在THUMB模式下,寄存器组R8-R15(被称为Hi-registers)不是标准寄存器组中的一部分。因此,汇编程序对他的访问是受限制的。但是他们可以用来作为临时的存放地。

可以使用mov指令,将R0-R7里面的值放置到高寄存器中。也可以将高寄存器中的值放到低寄存器中(R0-R7)

也可以使用CMP指令,将高寄存器和低寄存器进行比较

也可以使用ADD指令,将高寄存器中的值加到低寄存器中

1.8 程序状态寄存器

ARM920T 包含一个当前程序状态寄存器(CPSR),以及5个已经保存了的程序状态寄存器(SPSR)。这些寄存器的功能有:

  1. 保存执行单元(ALU)最近的信息
  2. 打开或者关闭中断
  3. 处理器运行模式
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
N Z C V - - - - - - - - - - - - - - - - - - - - I F T M4 M3 M2 M1 M0

条件码标识

N,Z,C,V是条件码的标志位。这些将会被算术和逻辑运算改变,然后再根据这些位来决定指令是否执行。

在arm状态下,所有的指令可以被条件的执行。

在thumb状态下,只有分支指令才可以按照条件执行

控制位

最低下的8位被称为控制位。当一个异常发生时,他们会被改变。如果处理器在特权模式下,那么他们也可以被软件手动改变。

描述
T 当为1时,处理器运行在THUMB模式下,否则运行在ARM模式下。他将影响TBIT外部信号
中断禁止位 I和F是中断禁止位。为1,则相应的禁止IRQ和FIQ
模式位 M4,M3,M2,M1,M0是模式位,如下表,只有下表出现的模式才是正确的模式,一旦程序设置了错误的模式,则会产生复位异常
保留位 剩下的位为保留位。
M[4:0] 模式 thumb模式下的寄存器 arm模式下的寄存器
10000 User R7…R0,LR,SP,PC,CPSR R14…R0,PC,CPSR
10001 FIQ R7…R0,LR_fiq,SP_fiq,PC,CPSR,SPSR_fiq R7…R0,R14_fiq…R8_fiq,PC,CPSR,SPSR_fiq
10010 IRQ R7…R0,LR_irq,SP_irq,PC,CPSR,SPSR_irq R12…R0,R14_irq,R13_irq,PC,CPSR,SPSR_iraq
10011 Supervisor R7…R0,LR_svc,SP_svc,PC,CPSR,SPSR_svc R12…R0,R14_svc,R13_svc,PC,CPSR,SPSR_svc
10111 Abort R7…R0,LR_abt,SP_abt,PC,CPSR,SPSR_abt R12…R0,R14_abt,R13_abt,PC,CPSR,SPSR_abt
11011 Undefined R7…R0,LR_und,SP_und,PC,CPSR,SPSR_und P12…R0,R14_und,R13_und,PC,CPSR
11111 System R7…R0,LR,SP,PC,CPSR R14…R0,PC,CPSR

1.9 异常

例如响应外设电路的中断,此时反生异常。在异常处理前,当前处理器的状态必须保存下来,目的是,当异常处理完成之后,可以继续执行

在同一时间,可能同时出现多个异常,此时他们以固定的顺序进行处理,详见下面的异常优先级。

进入异常时的操作

当处理异常时,ARM920T会做如下的操作:

  1. 在链接寄存器中保存下一个指令的地址。如果异常从arm状态进入,则下一个指令的地址被复制到链接寄存器中(即PC+4,或者PC+8,具体依赖于不同的异常,后面有详细说明)如果异常从THUMB状态进入,链接寄存器则保存当前PC的偏移量。这就意味着,异常处理程序,不用管,到底是从哪个状态进入的异常。
  2. 赋值CPSR到对应的SPSR
  3. 修改CPSR对应的模式位
  4. 修改PC为对应的异常向量地址

还可以设置异常禁止位,防止异常嵌套的发生

如果处理器在THUMB状态下,此时发生了异常,当PC指向异常向量的地址时,自动切为ARM状态

离开异常时的操作

异常处理程序完成后:

  1. 将链接寄存器的值,复制到PC中
  2. 复制SPSR到CPSR
  3. 如果允许中断,则清除中断禁止位,

异常入口/出口摘要

下表列出了异常发生时,保存在链接寄存器中的PC的值,以及退出异常处理程序的推荐的指令

返回的指令 arm R14_x thumb R14_x
BL;MOV PC,R14 PC+4 PC+2
SWI;MOVS PC,R14_svc PC+4 PC+2
UDEF;MOVS PC,R14_und PC+4 PC+2
FIQ;SUBS PC,R14_fiq,#4 PC+4 PC+4
IRQ;SUBS PC,R14_irq,#4 PC+4 PC+4
PABT;SUBS PC,R14_abt,#4 PC+4 PC+4
DABT;SUBS PC,R14_abt,#8 PC+8 PC+8
RESET;NA - -

FIQ

FIQ(快速中断异常)被设计来处理数据传输和信道处理。在arm模式下,保证有最小,且足够的寄存器可用,以达到最优的上下文切换

外部的nFIQ输入为低时,产生FIQ异常。根据ISYNC输入信号的状态,nFIQ的输入可以被处理为同步或异步。当ISYNC为低时,nFIQ和nIRQ被当做异步。同步的周期延迟发生在中断影响处理器流之前。

无论异常是从ARM状态还是thumb状态进入的,FIQ异常可以通过下面的指令退出异常处理流程:

SUBS PC,R14_fiq,#4

FIQ可以通过CPSR的F位来禁止(用户模式下无法操作)。如果F位为0,ARM920T在每条指令结束时检查FIQ同步器输出的低电平。

IRQ

IRQ就是常见的中断,它由nIRQ输入触发。IRQ的优先级比FIQ的优先级低并且当FIQ进入时,IRQ将被禁止。通过设置CPSR寄存器的I位,可以在任何时候在特殊模式下(非用户模式)禁止这个异常

可以执行下面的代码,返回异常:

SUBS PC,R14_irq,#4

Abort

当前内存访问无法完成时,产生一个Abort异常。它也可以由外部的ABORT输入产生。ARM920T在内存访问周期中,检查abort异常

两种abort异常:

  1. 预取址Abort:在指令预取址的时候发生
  2. 数据Abort:数据访问时发生

如果预取址Abort发生,则取到的指令被标记为非法指令,并且直到指令到达管道的头部才发生异常。

如果指令没有被执行,abort也不会产生,比如分支指令

如果数据abort发生,接下来会发生什么,则依赖于指令的类型:

  1. 但数据传输指令(LDR,STR)写会被修改的寄存器。abort异常处理程序必须清楚这一点
  2. 交换指令(swap)中止,就好像它没有被执行一样
  3. 块数据传输指令继续完成(LDM,STM)。如果回写位被置位,则基址寄存器被更新。如果指令要覆盖基址寄存器,则覆盖会被中止,以保证不会覆盖。一旦发生abort异常,所有的寄存器覆盖都会被中止。因此R15就会被保留

abort机制可以实现按需分页的虚拟内存系统。在这个系统中,处理器可以产生任意的地址。当数据地址无效时,内存管理单元(MMU)产生一个abort异常。然后abort异常处理程序找出abort的原因,让请求的数据可用,然后重新执行产生abort异常的指令。

应用程序不需要知道他可用的内存量,他的状态也不会受abort异常的任何影响

退出abort异常的指令为:

SUBS PC,R14_abt,#4;for a prefetch abort
SUBS PC,R14_abt,#8;for a data abort

然后恢复PC和CPSR,并且再次执行产生abort异常的指令

软件中断

软件中断(SWI)被用来进入Supervisor模式。软件中断通过下面的指令返回:

MOV PC,R14_svc

他们恢复PC和CPSR,然后继续执行SWI后面的指令

未定义指令

当arm920T无法处理一个指令时,产生一个未定义指令异常。这种机制可以被用来扩展THUMB和ARM指令的软件仿真。

可以执行下面的指令,退出异常:

MOVS PC,R14_und

恢复CPSR,然后执行产生未定义指令异常的下一条指令

异常向量表

下表展示了异常向量地址:

地址 异常 进入的模式
0x00000000 Rest Supervisor
0x00000004 Undefined instruction Undefined
0x00000008 Software Interrupt Supervisor
0x0000000C Abort(prefetch) Abort
0x00000010 Abort(data) Abort
0x00000014 Reserved Reserved
0x00000018 IRQ IRQ
0x0000001C FIQ FIQ

异常优先级

当同时产生异常时,系统以固定的顺序处理。

高优先级:

  1. Rest
  2. Data abort
  3. FIQ
  4. IRQ
  5. Prefetch abort

低优先级:

  • Undefined instruction,Software Interrupt

注意:并不是所有的异常都能同时发生
未定义指令和软件中断异常他们是互斥的

如果数据abort异常和FIQ异常同时发生,并且FIQ异常被允许,ARM920T进入数据abort异常处理程序,然后立刻去处理FIQ的异常。FIQ异常退出之后,继续在abort异常处理程序中执行。

数据abort的优先级高于FIQ是有道理的,他能够保证第一时间捕获到传输错误。进入这个异常的时间,应该加上FIQ的延迟。

中断延迟

如果FIQ打开,则最长的延时包括:传递给同步器(Tsyncmax)的最长请求时间,加上,最长的指令时间(Tldm),加上,数据abort进入的时间(Texc),加上FIQ进入的时间(Tfiq)。然后才是ARM920T在0x1c处执行。

Tsyncmax三个处理器周期,Tldm20个处理器周期,Texc3个处理器周期,Tfiq2个处理器周期。总共需要28个处理器周期。在一个连续的20Mhz的处理器上大约消耗1.4微秒。

最大的IRQ延迟计算方式跟上面类似。但是必须考虑到FIQ有更高的优先级,可以延迟任意时间进入IRQ异常处理程序。

FIQ和IRQ的最小时间则由Tsyncmin加上Tfiq组成,为4个处理器周期。

复位异常

当nREST输入为低时,ARM920T放弃执行指令,然后继续从递增的字地址中取指令。

当nRest再次变高,ARM920T:

  1. 将当前的PC和CPSR,写入到R14_svc和SPSR_svc。
  2. 将M[4:0]改为1011(supervisor模式),CPSR的I,F位置位,清楚CPSR的T位
  3. 将PC为0x00
  4. 在arm模式下,继续执行