【vfp精品源码栏目提醒】:本文主要为网学会员提供“【精品PDF】第五章 基于ARM的嵌入式程序设计 - 兰州大学 - 毕业设计”,希望对需要【精品PDF】第五章 基于ARM的嵌入式程序设计 - 兰州大学 - 毕业设计网友有所帮助,学习一下!
5 ARM 主要内容 ARM 汇编语言程序设计 C 与汇编语言混合编程 ARM 汇编语言编程示例 一、ARM 汇编语言程序设计 1、两种常用IDE简介 2、ADS/SDT下的伪操作 3、ARM汇编语言伪指令 4、ARM汇编语言的文件和语句 5、ARM汇编语言编程的几个问题 6、ARM汇编语言编程示例 1、两种常用 IDE 简介 ADS/SDT IDE开发环境它由ARM公司开发使用了CodeWarrior公司的编译器 集成了GNU开发工具的IDE开发环境它由GNU的汇编器as、交叉编译器gcc、和链接器ld等组成。
2、ADS/SDT 下的伪操作 ADS编译环境下的伪操作可分为以下几类 符号定义Symbol Definition伪操作 数据定义Data Definition伪操作 汇编控制Assembly Control伪操作 信息报告Reporting伪操作 其他Miscellaneous伪操作 伪操作 语法格式 作 用 GBLA GBLA Variable 声明一个全局的算术变量并将其初始化成0 GBLL GBLL Variable 声明一个全局的逻辑变量初始化成FALSE GBLS GBLS Variable 声明一个全局的字符串变量初始化成空串“” LCLA LCLA Variable 声明一个局部的算术变量并将其初始化成0 LCLL LCLL Variable 声明一个局部的逻辑变量初始化成FALSE LCLS LCLS Variable 声明一个局部的串变量并将其初始化成空串“” SETA SETA Variable expr 给一个全局或局部算术变量赋值 SETL SETL Variable expr 给一个全局或局部逻辑变量赋值 SETS SETS Variable expr 给一个全局或局部字符串变量赋值 RLIST name LISTlistof registers 为一个通用寄存器列表定义名称 CN name CN expr 为一个协处理器的寄存器定义名称 CP name CP expr 为一个协处理器定义名称 DN/SN name DN/SN expr DN/SN为一个双精度/单精度的
VFP寄存器定义名称 FN name FN expr 为一个FPA浮点寄存器定义名称 符号定义Symbol Definition伪操作 伪操作 语法格式 作 用 LTORG LTORG 声明一个数据缓冲池也称为文字池的开始 MAP MAP expr base-register 定义一个结构化的内存表Storage Map的首地址 FIELD label FIELD expr 定义一个结构化内存表中的数据域 SPACE label SPACE expr 分配一块连续内存单元并用0初始化 DCB label DCB expr 分配一段字节内存单元并用expr初始化 DCD/ DCDU label DCD expr 分配一段字内存单元 DCDO label DCDO expr 分配一段字对齐的字内存单元 DCFD/ DCFDU label DCFDU fpliteral 为双精度的浮点数分配字对齐的内存单元 DCFS/ DCFSU label DCFSU fpliteral 为单精度的浮点数分配字对齐的内存单元 DCI label DCI expr 在ARM代码中分配一段字对齐的内存单元 在Thumb代码中分配一段半字对齐的半字内存单元 DCQ/ DCQU label DCQU literal 分配一段以双字8个字节为单位的内存 DCW/ DCWU label DCWU expr DCW用于分配一段半字对齐的半字内存单元 数据定义Data Definition伪操作 伪操作 语法格式 作 用 IFELSE及ENDIF IF logical expression … ELSE … ENDIF 能够根据条件把一段源代码包括在汇编语言程序内或者将其排除在程序之外。
WHILE及WEND WHILE logical expression … WEND 能够根据条件重复汇编相同的一段源代码。
MACRO 、MEND及MEXIT MACRO label macroname parameterparameter… … 宏代码 MEND MACRO标识宏定义的开始MEND标识宏定义的结束。
MERIT用于从宏中跳转出去。
用MACRO和MEND定义的一段代码称为宏。
通过宏名来调用 汇编控制Assembly Control伪操作 伪操作 语法格式 作 用 ASSERT ASSERT logical expr 对汇编程序的第二遍扫描中如果其中ASSERT中条件不成立ASSERT伪操作将报告该错误信息 INFO INFO num-exprstr-expr 在汇编处理过程的第一遍扫描或者第二遍扫描时INFO伪操作报告诊断信息 OPT OPT n 通过OPT伪操作可以在源程序中设置列表选项 TTL TTL title 在列表文件的每一页的开头插入一个标题 SUBT SUBT subtitle 在列表文件的每一页的开头插入一个子标题 信息报告Reporting伪操作 伪操作 语法格式 作 用 CODE16 CODE16 告诉汇编编译器后面的指令序列为16位的Thumb指令 CODE32 CODE32 告诉汇编编译器后面的指令序列为32位的ARM指令 EQU name EQU exprtype 为数字常量和程序中的标号基于PC的值定义一个字符名称 AREA AREA nameattrattr… 定义一个代码段或者数据段 ENTRY ENTRY 指定程序的入口点 END END 告诉编译器已经到了源程序结尾 ALIGN ALIGN exproffset 通过添加补丁字节使当前位置满足一定的对齐方式 EXPORT/ GLOBAL EXPORT symbol WEAK 声明一个符号可被其他文件引用相当于声明了一个全局变量 IMPORT IMPORT symbol WEAK 告诉编译器当前的符号不是在本源文件中定义的而是在其他源文件中定义的在本源文件中可能引用该符号 EXTERN EXTERN symbol WEAK 告诉编译器当前的符号不是在本源文件中定义的而是在其他源文件中定义的在本源文件中可能引用该符号 GET/ INCLUDE GET filename 将一个源文件包含到当前源文件中并将被包含的文件在其当前位置进行汇编处理 INCBIN INCBIN filename 将一文件包含到当前源文件中被包含文件不进行汇编处理 KEEP KEEPsymbol 告诉编译器将局部符号包含在目标文件的符号表中 NOFP NOFP 禁止源程序中包含浮点运算指令 REQUIRE REQUIRE lable 指定段之间的相互依赖关系 RN name RN expr 为一个特定的寄存器定义名称 ROUT name ROUT 定义局部变量的有效范围 其他Miscellaneous伪操作 3、ARM 汇编语言伪指令 伪指令 语法格式 作 用 ADR ADRcond registerexpr 将基于PC或基于寄存器的地址值读取到寄存器中。
小范围的地址读取。
ADRL ADRLcond registerexpr 将基于PC或基于寄存器的地址值读取到寄存器中。
中等范围的地址读取。
LDR LDRcond registerexprlabel-expr 将一个32位的立即数或者一个地址值读取到寄存器中。
大范围的地址读取。
NOP NOP 在汇编时将被替换成ARM中的空操作。
4、ARM 汇编语言的文件和语句 源程序文件 文件名 说 明 汇编程序文件 .S 用ARM汇编语言编写的ARM程序或Thumb程序 C程序文件 .C 用C语言编写的程序代码 头文件 .H 为了简化源程序把程序中常用到的常量命名、宏定义、数据结构定义等等单独放在一个文件中一般称为头文件 ARM汇编语言语句格式如下所示 symbol instructiondirectivepseudo-instruction comment 其中 instruction为指令 directive为伪操作 pseudo-instruction为伪指令 symbol为符号 comment为语句的注释 ARM汇编语言是以段section为单位来组织源文件的。
段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。
一个ARM源程序至少需要一个代码段大的程序可以包含多个代码段和数据段。
ARM汇编语言源程序的基本结构举例 AREA ExampleCODEREADONLY ENTRY start MOV R040 MOV R123 ADD R0R0R1 END 程序体部分实现了一个简单的加法运算。
5、ARM 汇编语言编程的几个问题 ARM数据处理操作 设置条件码 汇编语言子程序调用及返回 跳转表思想 ARM与Thumb之间的状态转换及函数的互相调用 32位立即数在32位指令中的编码以及ARM特有的寄存器移位操作是数据处理方面的难点 ARM数据处理操作 ARM的任何数据处理指令都能通过增加“S”操作码来设置条件码N、Z、C、V。
每条指令都可以条件执行。
在程序中可以通过条件码的使用让微处理器决定是否进行转移还可用来控制循环的退出。
设置条件码 汇编语言子程序调用及返回 在ARM汇编语言中子程序调用是通过BL指令来完成的。
BL subname 其中subname是被调用的子程序的名称。
在返回调用子程序时转移链接指令保存到LR寄存器R14中的值需要拷贝回程序寄存器PCR15。
子程序返回的方法:对于最简单的子程序一条MOV指令就可以完成子程序的返回如下所示SUB2…MOVPCR14对于在子程序中出现嵌套调用时链接寄存器LR中的返回地址可能会在第二次调用时被覆盖所以需要将返回地址压入堆栈来进行保存SUB1STMFDR13R0 –R2R14BLSUB2…LDMFDR13R0 –R2PC跳转表思想 在程序设计中有时为使程序完成一定的功能需要调用一系列子程序中的一个而决定究竟调用哪一个由程序的计算值确定。
跳转表是解决该问题的有效方案。
跳转表是利用程序计数器PC在通用寄存器文件中的可见性来实现的如下例所示 BLJUMPTAB…JUMPTABADR R1SUBTABR1 取SUBTABCMPR0SUBMAX检查超限LDRLSPCR1R0LSL 2 若OK跳转到表中BERROR否则发出错误信息SUBTABDCDSUB0子程序表入口DCDSUB1DCDSUB2ARM与Thumb之间的状态转换及函数的互相调用 ARM/Thumb之间的函数调用时 在同一状态下的子程序调用、返回通常都只需要一条指令实现BL function 和 MOV PCLR 在不同状态下的子程序调用中就需要进行状态之间的切换需要考虑到以下几点 需要由BX来切换状态因为BL不能完成状态切换。
需要在BX之前先保存好LRBX不能自动保存返回地址到LR。
需要 用“BX LR”来返回不能使用“MOV PCLR”返回时要仔细考虑保存在LR中最低位是否正确。
6、ARM 汇编语言编程示例 AREA ARMexCODEREADONLY ENTRY start MOV R110 MOV R23 ADD R1R1R1 stop MOV R00x18 LDR R10x20026 SWI 0x123456 将CPU控制权交给调试器 END 示例 1简单的ARM指令程序 AREA BlockCODEREADONLY NUM EQU 20 ENTRY LDR R0 src LDR R1 dst MOV R2 NUM MOV SP 0x400 Bcopy MOVS R3 R2 LSR 3 BEQ Cword STMFD SP R4 - R11 Ocopy LDMIA R0 R4 - R11 STMIA R1 R4 - R11 SUBS R3 R3 1 BNE Ocopy 示例 2数据块批量复制程序一次8字不足则单字复制 LDMFD SP R4 - R11 Cword ANDS R2 R2 7 BEQ Stop Wcopy LDR R3 R0 4 STR R3 R1 4 SUBS R2 R2 1 BNE Wcopy Stop MOV R0 0x18 LDR R1 0x20026 SWI 0x123456 将CPU控制权交给调试器 AREA BdataDATAREADWRITE src DCD 12345678 12345678 1234 dst DCD 00000000 00000000 0000 END 二、C 与汇编语言混合编程 1、嵌入式C语言程序设计的几个问题 2、C与汇编语言混合编程及示例 1、嵌入式 C 语言程序设计的几个问题 ① 变量定义 ② 参数传递 ③ 循环条件 在变量声明的时候最好把所有相同类型的变量放在一起定义这样可以优化存储器布局。
由下例可以看出 对于局部变量类型的定义使用short或char来定义变量并不是总能节省存储空间。
有时使用32位int或unsinged int局部变量更有效率一些如下图所示 变量定义中为了精简程序程序员总是竭力避免使用冗余变量。
但有时使用冗余变量可以减少存储器访问的次数这可以提高系统性能。
示例二者在数据区里的布局分别是charashortbcharcintdcharacharcshortbintdabcdabcdpadpad不同类型局部变量的编译结果intwordincintareturn a1short shortincshorta return a1char charincchara return a1wordincADD a1a11shortincADD a1a11MOV a1a1.LSL 16MOV a1a1ASR 16charincADD a1a11AND a1a1ampFF① 变量定义 为了使各自单独编译的C语言程序和汇编程序能够互相调用定义了统一的函数过程调用标准ATPCS。
ATPCS规定寄存器组中的R0R3作为参数传递和结果返回寄存器如果参数数目超过四个则使用堆栈进行传递。
内部寄存器的访问速度是远远大于存储器的所以要尽量使参数传递在寄存器里面进行即应尽量把函数的参数控制在四个以下。
② 参数传递 ③ 循环条件 计数循环是程序中常用的流程控制结构一般有以下两种形式 for loop1loopltlimitloop for looplimitloop0loop-- 这两种循环形式在逻辑上并没有差别但是映射到具体的体系结构中时就产生了不同如下图所示 intFact1intlimit…for i1iltlimitifactfacti…intFact2intlimit…for i limit i0i--factfacti…Fact1……0x000010MUL R0R1R00x000014ADD R1R110x000018CMP R1R20x00001cBLE 0x10……0x000024MOV PCLRFact2……0x000010MUL R0R1R00x000014SUBS R1R110x000018BNE 0x10……0x000020MOV PCLR2、C 与汇编语言混合编程及示例 ① ATPCS 规则 ② 内嵌汇编 ③ C和ARM汇编程序间相互调用 ① ATPCS 规则 ATPCSARM-Thumb Produce Call Standard是ARM程序和Thumb程序中子程序调用的基本规则目的是为了使单独编译的C语言程序和汇编程序之间能够相互调用。
这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则和参数的传递规则。
寄存器 别名 特殊名 使用规则 R0 a1 参数/结果scratch寄存器1 R1 a2 参数/结果scratch寄存器2 R2 a3 参数/结果scratch寄存器3 R3 a4 参数/结果scratch寄存器4 R4 v1 ARM状态局部变量寄存器1 R5 v2 ARM状态局部变量寄存器2 R6 v3 ARM状态局部变量寄存器3 R7 v4 wr ARM状态局部变量寄存器4 R8 v5 ARM状态局部变量寄存器5 R9 v6 sb ARM状态局部变量寄存器6 R10 v7 sl ARM状态局部变量寄存器7 R11 v8 fp ARM状态局部变量寄存器8/帧指针 R12 ip 子程序内部调用的scratch寄存器 R13 sp 数据栈指针 R14 lr 连接寄存器 R15 pc 程序计数器 寄 存 器 的 使 用 规 则 根据堆栈指针指向位置的不同 和增长方向的不同可以分为以下4种数据栈 FD Full Descending 满递减 ED Empty Descending空递减 FA Full Ascending 满递增 EA Empty Ascending 空递增 ATPCS规定数据栈为FD满递减类型并且对数据栈的操作是8字节对齐的。
数据栈的使用规则 参数个数固定的子程序参数传递规则 第一个整数参数通过寄存器R0R3来传递。
其他参数通过数据栈传递。
参数个数可变的子程序参数传递规则 当参数不超过4个时可以使用寄存器R0R3来传递参数当参数超过4个时还可以使用数据栈来传递参数 子程序结果返回规则 结果为一个32位整数时可以通过寄存器R0返回结果为一个64位整数时可以通过寄存器R0和R1返回依次类推。
参数的传递规则 在C程序中嵌入汇编程序可以实现一些高级语言没有的功能并可以提高执行效率。
armcc和armcpp内嵌汇编器支持完整的ARM指令集tcc和tcpp用于Thumb指令集。
所以同一个C程序中不能同时包含ARM指令和Thumb指令。
内嵌的汇编指令包括大部分的ARM指令和Thumb指令但是不能直接引用C的变量定义数据交换必须通过ATPCS进行。
嵌入式汇编在形式上表现为独立定义的函数体。
② 内嵌汇编 内嵌汇编示例 include ltstdio.hgt void astrcpychar p1char p2 char tempch __asm loop:LDRB tempchp11 STRB tempchp21 CMP tempch0 BNE loop void main …定义并初始化str1、str2 …定义字符串tempstr __asm MOV R0str1 MOV R1str2 MOV R2tempstr BL astrcpyR0R2 BL astrcpyR1R0 BL astrcpyR2R1 ③ C和ARM汇编程序间相互调用 遵守ATPCS的前提下注意export和extern的配合使用 示例C程序调用汇编程序 include ltstdio.hgt extern void strcpychar char void main char src“source” char dst“destination” strcpydstsrc printf“snsn”srcdst area Scopycodereadonly export strcpy strcpy LDRB R2R11 STRB R2R01 CMP R20 BNE strcpy MOV PCLR end 示例汇编程序调用C程序 int gint aint bint cint dint e return abcde C程序用于计算五个数之和 汇编程序则把四个放入R0R3 最后一个放在数据栈内 编译器判断出需要几个参数 自动取得。
area fcodereadonly extern g STR LRSP-4 ADD R1R0R0 ADD R2R1R0 ADD R3R1R2 STR R3SP-4 ADD R3R1R1 BL g ADD SPSP4 LDR PCSP4 end 1、求两个向量的点积 2、SWI 软件中断 3、IRQ 中断 4、异常中断向量表的搬运 三、例程 1求两个向量的点积 include ltstdio.hgt define low32a unsigned ampa0 define high32a int ampa1 小端存储模式 void main int a10 12345678910 int b10 10987654321 printf“Dotprod is ld n” dotprodab10 __int64 dotprodint a int b unsigned n __int64 sum0 do sum mlalsum a b while--n0 return sum __int64 mlal__int64 sum int a int b __asm SMLAL low32sum high32sum a b return sum 例程 2SWI 软件中断 执行SWI指令时系统自动完成以下工作 R14_SVC SWI指令的下面一条指令的地址 SPSR_SVC CPSR CPSR4:0 0b10011 CPSR5 0 CPSR7 1 禁止响应 IRQ 中断 PC 0x00000008 SWI中断处理程序与系统相关的ARM指令代码 SWISTART: STMFD SP R0-R3 R12 LR MRS R0 SPSR TST R0 0x20 LDRNEH R0 LR -2 读SWI立即数 BICNE R0 R0 0xFF00 LDREQ R0 LR -4 BICEQ R0 R0 0xFF000000 CMP R0 MaxSWI 判断是否越界 LDRLS PC PC R0 LSL 2 B SWI_OutofRange 占4 个字节 SWITable: DCD DOSWI_0 DCD DOSWI_1 …… DOSWI_0: …… LDMFD SP R0-R3 R12 PC DOSWI_1: …… LDMFD SP R0-R3 R12 PC 例程 3IRQ 中断 响应IRQ中断请求时系统自动完成以下工作 R14_IRQ 当前PC8 SPSR_IRQ CPSR CPSR4:0 0b10010 CPSR5 0 CPSR7 1 禁止响应其他 IRQ 中断 PC 0x00000018 IRQ中断处理程序与系统相关的ARM指令代码 SUB R14 R14 4 前面加 8此处减 4 STMFD R13 R12 R14 MRS R12 SPSR 允许IRQ中断嵌套 STMFD R13 R12 MOV R12 IntBase 中断源提供功能号 LDR R12 R12 IntLevel MRS R14 CPSR 允许响应IRQ中断 BIC R14 R14 0x80 MSR CPSR_C R14 LDR PC PC R12 LSL 2 NOP 用于占4 字节而已 DCD INT0 DCD INT1 …… INT0: STMFD R13 R0-R11 …… MRS R12 CPSR ORR R12 R12 0x80 MSR CPSR_C R12 禁止响应IRQ中断 LDMFD R13 R0-R12 MSR SPSR_CXSF R12 LDMFD R13 R12 PC 逆序恢复现场 INT1: STMFD R13 R0-R11 …… 例程 4异常中断向量表的搬运 当操作系统配置为地址 0x0 处为RAM而不是ROM时在引导操作系统前应从ROM中搬运复制异常中断向量表到RAM以保证各异常的正常响应。
假定保存在ROM中的异常中断向量表和异常中断向量处理程序入口地址为 Export Int_Vectors 异常中断向量表 Int_Vectors: LDR PC Int_Table LDR PC Int_Table 4 LDR PC Int_Table 8 LDR PC Int_Table 12 LDR PC Int_Table 16 LDR PC Int_Table 20 LDR PC Int_Table 24 LDR PC Int_Table 28 Export Int_Table 异常中断处理程序的入口点函数 Int_Table: Int_Initialize_Addr DCD Int_Initialize Undef_Instr_.
上一篇:
【精品】物货管理系统 论文
下一篇:
猪疥癣病的防治