开课实验室: 嵌入式系统实验室 年 月 日
学院 | 年级、专业、班级 | 姓名 | |||
实验序号 | 实验项目名称 | RealView集成开发环境、ARM/ Thumb汇编指令,C语言与汇编语言综合应用实例 | 指导教师 | ||
实验类型 | 验证性实验( ) 设计性实验( ) 综合性实验( ) | 同组实验人 | 成绩 | ||
教师评语 | 教师签字: 年 月 日 | ||||
1、实验目标 1.初步学会使用 μVision3 IDE for ARM 开发环境及ARM 软件模拟器; 2.通过实验掌握简单 ARM 汇编指令的使用方法。用 μVision3 IDE for ARM 开发环境及ARM 软件模拟器; 3.通过实验掌握简单 ARM 汇编指令的使用方法。 4.通过实验掌握使用 ldm/stm,b,bl 等指令完成较为复杂的存储区访问和程序分支; 5.学习使用条件码,加强对 CPSR 的认识; 6.通过实验掌握msr/mrs指令实现ARM处理器工作模式的切换 7.观察不同模式下的寄存器,加深对CPU结构的理解 8.学会使用c与汇编混合编程 2、实验内容 1. 编写程序循环对R4-R11进行累加8次赋值,R4-R11 起始值为1-8,每次加操作后把R4-R11的内容放入SP 栈中,SP 初始设置为0x800。 最后把R4-R11用LDMFD指令清空赋值为0。 2.编写程序从ARM状态切换到Thumb,在ARM状态下把R2赋值为0x12345678,在Thumb状态下把R2赋值为0x87654321。同时观察并记录CPSR,SPSR的值,分析各个标志位。 3.有两个内存区A,B,内存区A存放100个字(32位),有两个函数分别为Fiq_get()FIQ模式,和用户模式Sort(); Fiq_get()负责从前到后从A区取8个字 W0-W7,并全部减去第8个数W8,再传递给Sort()函数 ;Sort()接收(调用) Fiq_get()的数,并插入B区进行排序,排序后的数仍存放在B区 要求用Fiq_get()用汇编实现,Sort()用C实现,要求利用FIQ模式和用户模式的自有寄存器实现数据传递和保存的最大效率 3、实验原理 1. ARM寄存器数据传送 ARM通用寄存器(R0-R15)可分为三类: (1)不分组寄存器R0-R7; 不分组寄存器R0~R7在所有处理器模式下,它们每一个都访问一样的32 位寄存器。它们是真正的通用寄存器,没有体系结构所隐含的特殊用途。 (2)分组寄存器 R8-R14; 分组寄存器R8~R14 对应的物理寄存器取决于当前的处理器模式。若要访问特定的物理寄存器而不依赖当前的处理器模式,则要使用规定的名字。寄存器R8~R12 各有两组物理寄存器:一组为FIQ 模式,另一组为除了FIQ 以外的所有模式。 寄存器R8~R12 没有任何指定的特殊用途,只是在作快速中断处理时使用。寄存器 R13,R14 各对应6 个分组的物理寄存器,1 个用于用户模式和系统模式,其它5 个分别用于5 种异常模式。寄存器R13 通常用做堆栈指针,称为SP;寄存器R14 用作 子程序链接寄存器,也称为LR。 (3)程序计数器R15。 寄存器R15 用做程序计数器 (PC)。 在本实验中,ARM 核工作在用户模式,R0~R15 可用。 本题涉及到的汇编指令语法及规则: ldr ldr 伪指令将一个32 位的常数或者一个地址值读取到寄存器中。当需要读取到寄存器中的数据超过了mov 或者mnv 指令可以操作的范围时,可以使用ldr 伪指令将该数 据读取到寄存器中。在汇编编译器处理源程序时,如果该常数没有超过mov 或者mnv 可以操作的范围,则ldr 指令被这两条指令中的一条所替代,否则,该常数将被放在最 近的一个文字池内(literal pool),同时,本指令被一条基于PC 的ldr 指令替代。 语法格式: ldr 其中,expression 为需要读取的32 位常数;register 为目标寄存器。 示例: ldr r1,=0xff ldr r0,=0xfff00000 本题部分程序解析: mov sp,#stack_top ;堆栈头 ldr r0,=source ;初值 mov r1,#number ;循环次数 ldr r2,=reset ;复位置零 LDMIA r0!,{R4-R11} ;将R0指向的地址单元中的数据读出到R4到R11 stmia sp!,{r4-r11} ;将R4到R11单元中的值压入堆栈 ldmfd r2,{r4-r11} ;将R2所指向单元的值读出到R4到 R11 2.ARM指令状态切换ARM/Thumb (1)ARM 处理器共有两种工作状态: ARM:32 位,这种状态下执行字对准的ARM 指令; Thumb:16 位,这种状态下执行半字对准的Thumb 指令。 在 Thumb 状态下,程序计数器PC 使用位1 选择另一个半字。 注意: ARM 和Thumb 之间状态的切换不影响处理器的模式或寄存器的内容。 ARM 处理器在两种工作状态之间可以切换。 图3-7 寄存器状态图 (2)程序状态寄存器 前一节提到的程序状态寄存器CPSR和SPSR包含了条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。每种异常模式都有一个程序状态保存寄存器CPSR。当异常出现时,SPSR用于保留CPSR的状态。 CPSR 和SPSR 的格式如下: 1) 条件码标志: N,Z,C,V 大多数指令可以检测这些条件码标志以决定程序指令如何执行 2) 控制位: 最低 8 位 I,F,T 和M 位用作控制位。当异常出现时改变控制位。当处理器在模式下也可以由软件改变。 ●中断禁止位:I置1 则禁止IRQ中断;F置1 则禁止FIQ 中断。 ●T位:T=0指示ARM 执行;T=1指示Thumb执行。在这些体系结构的系统中,可自由的使用能在ARM和Thumb状态之间切换的指令。 模式位:M0,M1,M2,M3和M4是模式位.这些位决定处理器的工作模式.如表12-1 所示。 3) 其他位 程序状态寄存器的其他位保留,用作以后的扩展。 (3)本实验涉及到的伪操作及指令规则 Code [16|32] code 伪操作用于选择当前汇编指令的指令集。参数16 选择Thumb 指令集,参 数32 选择ARM 指令集。 语法格式: code[16|32] adr adr 指令将基于PC 的地址值或者基于寄存器的地址值读取到寄存器中。在汇编编 译器处理源程序时,adr 伪指令被编译器替换成一条合适的指令。通常,编译器 用一条add 指令或者sub 指令来实现该伪指令的功能。如果标号超出范围或者标 号在同一文件(和同一段)内没有定义,则会产生一个错误。该指令不使用文字池 (literal pool)。 Bx{ Bx指令实现跳转到Rn指定的地址去执行程序。若Rn的bit0为1,则跳转时自动将CPSR中的标志T置位,即把目标地址的代码解释为Thumb代码;若Rn的bit0为0,则跳转时自动将CPSR中的标志T复位,即把目标地址的代码解释为ARM代码。 (4) 本题部分程序解析: adr r0,TSTART+1 ;根据CPSR值可知处于arm态,管理模式 ldr r2,=number_1 bx r0 ;跳转并切换为Thumb工作状态 3.ARM处理器模式转换及C与汇编混合编程 (1) ARM 体系结构支持下表3-2 所列的7 种处理器模式。 在软件控制下可以改变模式,外部中断或异常处理也可以引起模式发生改变。 大多数应用程序在用户模式下执行。当处理器工作在用户模式时,正在执行的程序不能访问某些 被保护的系统资源,也不能改变模式,除非异常(exception)发生。这允许通过合适地编写操作系统来控制系统资源的使用。 除用户模式外的其他模式称为模式。它们可以自由的访问系统资源和改变模式。 (2) ARM异常向量表 当正常的程序执行流程暂时挂起时,称之为异常,例如:处理一个外部的中断请求。在处理异常之前,必须保存当前的处理器状态,以便从异常程序返回时可以继续执行当前的程序。ARM 异常向量表如下: 处理器允许多个异常同时发生,这时,处理器会按照固定的顺序进行处理,参照下面的异常优先级。 高优先级: 1 ---- Reset 2 ---- Data abort 3 ---- FIQ 4 ---- IRQ 5 ---- Prefetch abort 低优先级: 6 ---- Undefined Instruction,Software interrupt 由上可见,Reset 入口,即为整个程序的实际入口点。因此,我们在编写代码的时候,第一条语句是在0x00000000 处开始执行的. (3) 内嵌汇编语言 编译 C 时,可以通过__asm 汇编程序说明符调用内嵌汇编程序。说明符后面跟随有一列包含在大括号中的汇编程序指令。例如: __asm { Instruction [; instruction] ... [instruction] } 如果两条指令在同一行中,必须用分号将其分隔。如果一条指令占用多行,必须用反斜线符号(\)指定续行。可在内嵌汇编语言块内的任意位置处使用C 注释。可在任何可以使用C 语句的地方使用 __asm 语句。 (4) 本题部分程序解析 I1)工作模式切换 由于程序运行开始工作在用户模式,不能从用户模式直接切换到其他模式,必须先通过mainfunc内嵌的汇编程序swi进行软中断,从而切换到模式。再通过msr/mrs指令对CPSR的M0-M4位进行操作,切换到FIQ模式进行数据传送。 b mainfunc ; C程序: void mainfunc() { //fiqfunc(); __asm { SWI 0 } fiqfunc(); } tofiq mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0x11 ;/* set the mode as FIQ mode */ msr cpsr_cxfs,r0 数据传送之后转换成用户模式: mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0x10 ;/* set the mode as user mode */ msr cpsr_cxfs,r0 I2)汇编中调用c程序 ldr r0, =src ;/* A区地址传递*/ ldr r1, =dst ;/* B区地址传递*/ b sort ;调用c排序 C排序程序: void sort( const int *src,int *dest) { int j,i,temp; for(i=0;i<19;i++) for(j=i+1;j<20;j++) { if(dest[i]>dest[j]) { temp=dest[i];dest[i]=dest[j];dest[j]=temp; } } } 四、实验设备 (软、硬件) 1.pc机 2.Keil μVision3 IDE for ARM 5、实验步骤 1)在\\Keil\\ARM\\Examples\目录下建立文件夹命名,参考3.1.5 小节实验的操作步骤建立一个新的工程,命名; 2)在Project workspace 工作区中右击target1->Source Group 1,在弹出菜单中选择“Add file to Group ‘Source’ ”,在随后弹出的文件选择对话框中,选择刚才建立的源文件; 3) 把光盘\\software\\EduKit44B0_for_MDK\\common 目录中的DebugINRam.ini 文件拷贝到\\Keil\\ARM\\Examples\\Armcode1 目录下。选择菜单项Project->Option for Target…,将弹出工程设置对话框,设置与3.1.5 小节实验中的工程配置相同。 4)选择菜单项Project ->Build target 或快捷键F7,生成目标代码; 5)选择菜单项Debug ->Start/Stop Debug Session 或快捷键 Ctrl+F5,即可进入调试模式。这里使用的是μVision3 IDE 中的软件仿真器; 6)选择菜单项Debug ->run 或F5,即可运行代码; | |||||