




已阅读5页,还剩110页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1 第5章ARM指令集和汇编语言程序 本章主要介绍以下内容 ARM汇编语言程序格式典型ARM汇编语言程序举例ARM汇编与C C 混合编程 2 嵌入式系统开发中汇编语言设计的意义 汇编语言程序设计更能充分发挥处理器的硬件特性两个优势操作系统移植需要编写几百行底层硬件的汇编语言程序 这是C语言不可取代的 优化算法的时空效率 C语言的目标代码优化是编译器完成的 而汇编语言的目标代码优化是人工完成的 人是算法的创造者 也是编译器的设计者 人工优化比编译器质量高 弱点编程效率低 开发周期长 经济代价大 3 5 1ARM汇编语言程序格式 两种ARM汇编语言格式ARM汇编语言程序格式主要有两种 基于ADS1 2集成开发环境的汇编器格式包括SDT在内 统称为ADS基于Linux的GNU汇编器格式在本章主要介绍基于ARM公司ADS集成开发环境汇编器格式的汇编语言程序设计 在后面将介绍基于GNU汇编器的ARM汇编语言程序编写方法 4 预定义寄存器名及内部变量名 ARM汇编器中将几十个寄存器名称作为保留字预先给与了定义 这些预定义寄存器名都是大小写敏感的 它们都与具体的寄存器一一对应 参看下面的表格 5 ARM公司ADS预定义的寄存器名一览表 6 ARM公司ADS预定义的寄存器名一览表 续 7 ARM汇编语言程序的部分内部变量名清单 8 ARM汇编语言程序的语句格式 ARM汇编语言程序的语句格式格式如下 symbol instruction directive pseudo instruction comment 对应的中文语句格式描述是 符号 标号 指令 指示符 伪指令 注释 语句格式中 花括号括起来的部分表示可以省略 竖线分隔的字段表示可以替换 9 ARM汇编语言程序中的符号 ARM汇编语句中的符号可以是指令地址或标号 变量 常量和局部标号 符号属性可以是程序相关的 寄存器相关的或者是绝对地址 10 一 符号命名和书写规则 符号的命名和书写有以下规则 符号命名可以使用大小写字母 数字和下划线 符号是大小写字母敏感的 除本地行号外 名称不能以数字开头 一个程序段中不能重名 符号在其作用范围内必须唯一 符号不能够与系统内部变量或者系统预定义的符号同名 例如 a1orR0 sp cpsr PC or VAR or CONFIG CPU 等等 11 符号命名和书写规则 续 当程序中的符号与指令助记符或者指示符同名时 用双竖线将符号括起来 如 buffe a 这时双竖线并不是符号的组成部分 在ARM汇编语言程序中 所有符号必须在一行的最左边位置开始书写 即所谓的顶格书写 不允许包含空格或者制表符 符号的字符序列中不能大小写字母相混杂 12 二 常量 ARM汇编语言中使用到的常量可以是数字常量 字符常量 字符串常量和布尔常量 数字常量有以下3种表示方式 1 十进制数 如 535 246 2 十六进制数 如 0 x645 0 xff00 3 n进制数 格式为n XXX 其中n表示n进制 从2 9 XXX是具体的数字 例如 8 3777 8 5237702 数字常量 13 字符常量 字符常量由一对单引号括起来 包括一个单字符或者标准C中的转义字符 例如 A n 字符串常量由一对双引号以及由它括住的一组字符串组成 包括标准C中的转义字符 如果需要使用双引号或字符 则必须用 和 代替 例如执行语句 strtwoSETS Thisischaracterof 其编译结果是 字符串 Thisischaracterof 被赋值给strtwo变量 14 在汇编语句中的使用举例 GBLSadd4ffadd4ffSETS ADDr4 r4 0 xFF setupadd4ff add4ff 00 invokeadd4ff thisproduces ADDr4 r4 0 xFF00 elaboratesubstitutionGBLSs1GBLSs2GBLSfixupGBLAcountcountSETA14s1SETS a b count s1nowhasvaluea b0000000Es2SETS abc FixupSETS xy s2 z fixupnowhasvalue xyabcz C code MOVr4 16 butthelabelhereisC code 15 逻辑值常量 布尔常量TRUE和FALSE在表达式中写为 TRUE FALSE 16 三 表达式 ARM汇编语言中的表达式由符号 数值 单目操作符 双目操作符以及括号组成 运算的优先级次序与标准C一样 17 字符串表达式 字符串由字符串常量 字符串变量 操作符以及括号组成 最大长度为512字节 最短0个字节 字符串表达式的组成元素有 字符串常量 字符串变量 操作符等 字符串常量由包含在双引号内的一系列字符组成 当在字符串中包含美元符号 或者引号 时 用 表示一个 用 表示一个 字符串变量用指示符GBLS 全局字符串 或者LCLS 局部字符串 声明 用SETS赋值 取值范围与字符表达式相同 18 ARM汇编语言中的字符串操作符 19 指令格式说明 LENX 返回X字符串长度STRM 将数字M转换成一个字符串XRIGHTN 返回X字符串右边长度为N的子串XLEFTN 返回X字符串左边长度为N的子串CHRM 返回数字M表示的单个字符XCCY 返回字符串X和Y连接的字符串 20 数字表达式 数字表达式由数字常量 数字变量 操作符和括号组成 数字表达式表示的是一个32位数的整数 其取值范围为0 232 1 当作为有符号数时 其取值范围为 231 231 1 汇编器对 n和232 n不做区别 汇编时对关系运算符采用无符号数方式处理 这就意味着0 1是 FALSE 21 逻辑表达式 逻辑表达式由逻辑常量 逻辑操作符 关系操作符以及括号组成 取值范围为 FALSE 和 TRUE 22 四 地址标号 当符号代表地址时称为标号 Label 以数字开头的标号其作用范围是当前段 没有使用ROUT指示符时 这种标号又称为局部标号 LocalLabel 23 三种类型标号 1 PC相关标号 2 寄存器相关标号 3 绝对地址 24 PC相关标号 PC相关标号表示程序计数器加减一个数值常数后得到的地址值 常用来指明一个分支指令的目标地址 或者访问嵌入在代码段中的一个数据项 具体标记方法是 在汇编语言程序指令的前面写入标号 或者在一个数据指示符前面写入标号 通常用DCB或者DCD等指示符定义 25 DCB DCD指令格式 XDCBEXP1 EXP2 如定义一个字节为单位的标号XSTRDCB HELLOWORLD 0DCB0 x32 0 x34 0 x35XDCDEXP1 EXP2 定义一个字为单位的标号LDRPC RESETADDR RESETADDRDCDRESET RESET 26 寄存器相关标号 寄存器标号表示指定寄存器的值加减一个数值常数后得到的地址值 常常用于访问位于数据段中的数据 通常用MAP或者FIELD等指示符定义 格式 MAPEXPR BASE REG LABLE FIELDEXPR如 MAP0 x00400000 R9COUNTFIELD4XFIELD8YFIELD8 27 绝对地址 绝对地址是一个32位的无符号数字常量 可寻址范围是0 231 1 使用它可以直接寻址整个地址空间 28 五 段内标号和段外标号 ARM处理器的地址标号分为段内标号和段外标号 段内标号的地址值在汇编时确定 段外标号的地址值在连接时确定 29 程序相对寻址和寄存器相对寻址 在程序段中标号代表其所在位置与段首地址的偏移量 根据程序计数器和偏移量计算地址称为程序相对寻址 在映像文件中定义的标号代表标号到映像首地址的偏移量 映像的首地址通常被赋予一个寄存器 根据该寄存器值与偏移量计算地址称为寄存器相对寻址 30 六 局部标号 ARM汇编语言的宏常常使用局部标号 局部标号提供分支指令在汇编程序的局部范围内进行跳转 主要用途是汇编子程序中的循环和条件编码 它是一个0 99之间的数字 后面可以有选择地附带一个符号名称 局部标号特别适用于宏 31 局部标号 续1 使用ROUT指示符可以限制局部标号的范围 只能在该局部标号的范围引用局部标号 如果在该范围的上下两个方向都没有匹配的标号 汇编器将给出一个错误信号并停止汇编 局部标号语法格式如下 n routname 被引用的局部标号语法规则是 F B A T n routname 32 局部标号 续2 n是局部标号的数字号 routname是当前局部范围的名称 表示引用操作 F指示汇编器只向前搜索B指示汇编器只向后搜索A指示汇编器搜索宏的所有嵌套层次T指示汇编器搜索宏的当前层次如果F和B都没有指定 则汇编器首先向前搜索 再向后搜索 如果A和T都没有指定 汇编器搜索从宏的当前层次到宏的最高层次 比当前层次低的宏不再搜索 33 ARM汇编语言程序编写规范 ARM汇编语言程序源代码中允许有空行 可以在汇编程序中加上一个空白行 来增加程序的可阅读性 此外需要注意的是 指令 指示符 伪指令前必须加空格或者Tab制表符 这就是说指令 指示符 伪指令不可以从行的最左边开始书写 即不能顶格书写 在ARM汇编语言程序中 所有标号必须在一行的最左边的位置开始书写 标号的后面不要加 指令 指示符 寄存器名可以用小写字母也可以用大写字母来表示 但不能大小写字母相杂 34 ARM汇编语言程序编写规范 续 当一行写不下时 可以用反斜线 作为这一行最后的符号 然后另起一行接下去写 这样汇编器会将这两行代码看作一行代码 需要注意的是 如果在被引号括住的字符串中使用反斜线 则反斜线 不能起到续行的作用 每行的长度限制一般在128 255个字符串之间 分号 除非在字符串常量中出现 否则它的出现就表示着注释的开始 此注释直至行尾结束 可以将注释单独列为一行 所有注释被汇编器忽略 35 汇编语句规则举例 AREAStartup Code READONLYSTR1SETS ThisisanARMprocessor SENTBLDRR3 BLKADDRESSANDSR2 R2 0X40FIELD4 AREARRoutineA Code READONLYMOVR10 0XFF00SUB1MOVR6 100SEC MOVR8 0X200FloopMovR2 3BLoop 36 5 1 4ARM汇编语言指示符 ARM汇编语言程序指示符的英文原文是directive ARM指示符相当于x86处理器汇编语言程序中的伪指令 ARM指示符语句与ARM机器指令不存在一一对应的关系 它指示汇编器在汇编目标代码时进行变量定义 存储单元分配等操作 ARM指示符大致可以分成6种类型 分别是 符号定义 数据定义 汇编控制 框架控制 信息报告和杂项 37 AREA指示符用于定义一个代码段或者数据段 语法格式AREAsectionname attr attr 其中 sectionname为所定义的代码段或者数据段的名称 如果该名称是以数字开头的 则该名称必须用 括起来 如 1 datasec 还有一些代码段具有约定的名称 如 text 表示C语言编译器产生的代码段或者是与C语言库相关的代码段 Attr是该代码段 或者程序段 的属性 在AREA指示符中 各属性间用逗号隔开 一 AREA指示符 38 AREA的属性 下面列举主要的属性 ALIGN expression 默认的情况下 ELF的代码段和数据段是4字节对齐的 Expression可以取0 31的数值 相应的对齐方式为 2expression 字节对齐 如expression 3时为8字节对齐 ASSOC section 指定与本段相关的ELF段 任何时候连接section段也必须包括sectionname段 CODE定义代码段 默认属性为READONLY COMDEF定义一个通用的段 该段可以包含代码或者数据 在个源文件中 同名的COMDEF段必须相同 39 AREA的属性 续 COMMON定义一个通用的段 该段不包含任何用户代码和数据 连接器将其初始化为0 各源文件中同名的COMMON段公用同样的内存单元 连接器为其分配合适的尺寸 DATA定义数据段 默认属性为READWRITE NOINIT指定本数据段仅仅保留了内存单元 而没有将各初始值写入内存单元 或者将个内存单元值初始化为0 READONLY指定本段为只读 代码段的默认属性为READONLY READWRITE指定本段为可读可写 数据段的默认属性为READWRITE 40 AREA指示符举例 举例下面的指示符定义了一个代码段 代码段的名称为Mainpro 属性为READONLY AREAMainpro CODE READONLY codesegment 41 二 ENTRY指示符 ENTRY指示符指定程序的入口点语法格式ENTRY使用说明一个程序 可以包含多个源文件 中至少要有一个ENTRY 可以有多个ENTRY 但一个源文件中最多只能有一个ENTRY 可以没有ENTRY 示例AREAexample CODE READONLYENTRY 应用程序的入口点 42 三 CODE16和CODE32指示符 CODE16指示符告诉汇编编译器后面的指令序列为16位的Thumb指令 CODE32指示符告诉汇编编译器后面的指令序列为32位的ARM指令 语法格式CODE16 CODE32使用说明当汇编源程序中同时包含ARM指令和Thumb指令时 使用CODE16指示符告诉汇编编译器后面的指令序列为16位的Thumb指令 使用CODE32指示符告诉汇编编译器后面的指令序列为32位的ARM指令 但是 CODE16指示符和CODE32指示符只是告诉编译器后面指令的类型 该指示符本身并不进行程序状态的切换 43 CODE16 CODE32举例 在下面的例子中 程序先在ARM状态下执行 然后通过BX指令切换到Thumb状态 并跳转到相应的Thumb指令处执行 在Thumb程序入口处用CODE16指示符标识下面的指令为Thumb指令 参看下面的指令段 AREAChangeState CODE READONLYCODE32 指示下面的指令为ARM指令LDRr0 start 1BXr0 切换到Thumb 并跳转到start处执行CODE16 指示下面的指令为Thumb指令startMOVr1 10 44 四 EQU指示符 EQU指示符为数字常量 基于寄存器的值和程序中的标号 基于PC的值 定义一个字符名称 是EQU的同义词 语法格式nameEQUexpr type 其中 expr为基于寄存器的地址值 程序中的标号 32位的地址常量或者32位的常量 name为EQU指示符为expr定义的字符名称 type当expr为32位常量时 可以使用type指示expr表示的数据的类型 45 EQU 续 type有下面3种取值 CODE16CODE32DATA使用说明EQU指示符的作用类似于C语言中的 define 用于为一个常量定义字符名称 示例abcdEQU2 定义abcd符号的值为2abcdEQUlabel 16 定义abcd符号的值 label 16 addr1EQU0 xlC CODE32 定义addr1符号值为 绝对地址值0 xlC 而且该处为ARM指令 46 五 ROUT指示符 ROUT指示符用于标记局部标号使用范围的边界 用法如下 NAME ROUT使用说明 NAME是指定作用范围的名称使用ROUT指示符用于规定局部标号的使用范围 避免无意之中用错局部标号导致的越界 如 SUB1ROUT SUB1ROUT 47 ROUT 续 ROUTAROUT 定义局部标号有效范围 名称为ROUTA 3ROUTA 定义ROUTA中的局部标号3 BEQ 4 若条件成立 则跳转到局部标号4的位置 BEQ 3 若条件成立 则跳转到局部标号3的位置 4ROUTA 定义ROUTA中的局部标号4 OTHERPROGROUT 定义新的局部标号有效范围 48 六 END指示符 END指示符告诉编译器已经到了源程序结尾 语法格式 END使用说明 每一个汇编源程序都包含END指示符 以告诉本源程序的结束 示例 AREAexampleCODE READONLY END 49 七 ALIGN指示符 ALIGN指示符通过添加补丁字节使当前位置满足一定的对齐方式 语法格式ALIGN expr offset 其中 expr为数字表达式 用于指定对齐方式 可能的取值为2的次幂 如1 2 4 8等 如果指示符中没有指定expr 则当前位置对齐到下一个字边界处 offset为数字表达式 表示当前位置到下一个地址之间按照 offset n expr的方式进行对齐 50 ALIGN 续1 使用说明下面的情况中 需要特定的地址对齐方式 Thumb的宏指令ADR要求地址是字对齐的 而Thumb代码中地址标号可能不是字对齐的 这时就要使用指示符ALIGN4使Thumb代码中的地址标号字对齐 由于有些ARM处理器的CACHE采用了其他对齐方式 如16字节的对齐方式 这时使用ALIGN指示符指定合适的对齐方式可以充分发挥该CACHE的性能优势 LDRD及STRD指令要求内存单元是8字节对齐的 这样在为这两个指令分配的内存单元前要使用ALIGN8实现8字节对齐方式 地址标号通常自身没有对齐要求 而在ARM代码中要求地址标号是字对齐的 在Thumb代码中要求字节对齐 这样需要使用合适的ALIGN指示符来调整对齐方式 51 八 DCB指示符 DCB用于在内存中分配一个字节单元或者一组字节单元 并用指定的EXPR对其进行初始化语法格式 label DCB u expr expr label 是可选项 expr为 128 255的值或字符串 例 AREADCB EXAMPLE CODEDCB1ALIGN4 2DCB1Prompt1DCB NOWtheinformationmanagementsystemisrunning 0 52 九 MAP指示符 MAP用于将一个结构化内存的首地址映射到一个指定地址 是MAP的同义词语法格式 MAPexpr base register 当只有expr时 expr表示此内存首地址的值 当包括base register时内存首地址值为base register expr如MAP0 x00 r9 表示结构化内存首地址为r9 0timerFIELD4 表示一个数据域timer长度4字节 53 十 FIELD指示符 FIELD用于定义一个结构化内存区域中的数据域 常与MAP联合使用 是FIELD的同义词 语法格式 label FIELDexprlabel是当前数据域的一个标号 expr是当前数据域的长度例 YEARFIELD4 数据域YEAR4字节MONTHFIELD2 数据域MONTH2字节DAYFIELD2 数据FIELD2字节 54 十一 SPACE指示符 SPACE用于分配一个全0的内存区域 是SPACE的同义词 语法格式 label SPACEexpr label 是该内存域的标识 expr表示本内存空间的大小 以字节为单位 例 data timerSPACE0 x1000 定义一个4K字节的内存空间 初值为0ALIGN 恢复字对齐 55 课后练习P17711 请注释以下每条指令1 GBLSadd4ffadd4ffSETS ADDr4 r4 0 xFF add4ff 002 xyzROUT3xyz B F3 zxxROUT 56 AAPCS 2007年ARM公司正式推出了AAPCS标准ARMArchtectureProcedureCallStandardAAPCS是ATPCS的改进版目前 AAPCS和ATPCS都是可用的标准 57 AAPCS和ATPCS规范要点 寄存器的使用规则堆栈使用规则参数传递规则 58 ATPCS ATPCS ARM ThumbProcedureCallStandard 规定了一些子程序间调用的基本规则 这些规则包括子程序调用过程中寄存器的使用规则 数据栈的使用规则 参数的传递规则 有了这些规则之后 单独编译的C语言程序就可以和汇编程序相互调用 使用ADS的C语言编译器编译的C语言子程序满足用户指定的ATPCS类型 而对于汇编语言来说 则需要用户来保证各个子程序满足ATPCS的要求 59 寄存器的使用规则 子程序间通过寄存器R0 R3来传递参数 这时 寄存器R0 R3可记作a0 a3 被调用的子程序在返回前无需恢复寄存器R0 R3的内容 在子程序中 使用寄存器R4 R11来保存局部变量 这时 寄存器R4 R11可以记作v1 v8 如果在子程序中使用了寄存器v1 v8中的某些寄存器 则子程序进入时必须保存这些寄存器的值 在返回前必须恢复这些寄存器的值 在Thumb程序中 通常只能使用寄存器R4 R7来保存局部变量 寄存器R12用作过程调用中间临时寄存器 记作IP 在子程序之间的连接代码段中常常有这种使用规则 60 寄存器的使用规则 续 寄存器R13用作堆栈指针 记作SP 在子程序中寄存器R13不能用作其他用途 寄存器SP在进入子程序时的值和退出子程序时的值必须相等 寄存器R14称为连接寄存器 记作LR 它用于保存子程序的返回地址 如果在子程序中保存了返回地址 寄存器R14则可以用作其他用途 寄存器R15是程序计数器 记作PC 它不能用作其它用途 61 堆栈使用规则 ATPCS规定堆栈为FD类型 即满递减堆栈 并且对堆栈的操作是8字节对齐 对于汇编程序来说 如果目标文件中包含了外部调用 则必须满足下列条件 1 外部接口的堆栈必须是8字节对齐的 2 在汇编程序中使用PRESERVE8伪指令告诉连接器 本汇编程序数据是8字节对齐的 62 参数传递规则 如果系统不包含浮点运算的硬件部件 浮点参数会通过相应的规则转换成整数参数 若没有浮点参数 此步省略 然后依次将各字数据传送到寄存器R0 R3中 如果参数多于4个 将剩余的字数据传送堆栈中 入栈的顺序与参数顺序相反 即最后一个字数据先入栈 在参数传递时 将所有参数看作是存放在连续的内存字单元的字数据 63 子程序结果返回规则 子程序中结果返回的规则如下 结果为一个32位整数时 可以通过寄存器R0返回 结果为一个64位整数时 可以通过寄存器R0和Rl返回 结果为一个浮点数时 可以通过浮点运算部件的寄存器f0 d0或s0来返回 结果为复合型浮点数 如复数 时 可以通过寄存器f0 fn或d0 dn来返回 对于位数更多的结果 需要通过内存来传递 64 一 条件执行举例 求a和b两整数最大公约数的C程序While a b If a b a b elseb a 5 2典型ARM汇编语言程序举例 65 条件执行举例 续 如果用ARM汇编子程序来实现 就是求r1和r2两个寄存器中的两个整数的最大公约数 使用条件执行指令表示只有以下4句代码 gcdcmpr1 r2 cmp与subs功能类似subgtr1 r1 r2 如果r1 r2执行此指令subltr2 r2 r1 如果r1r2则转gcd标号注 函数结束时r1 r2 都可以用作返回值 66 二 32位地址送入一个寄存器中 下面指令段中的load指令根据输入参数决定调用那个函数 具体做法是将函数的绝对地址通过LDR指令存入在r4寄存器中 由于是32的绝对地址 LDR会被解释成以下操作 将函数的绝对地址放入一个文字池 Literalpool 嵌入在代码中的用以存放常数的区域 产生一条形如 LDRrn pc offsettoliteralpool 的指令来将这个绝对地址读入到指定的寄存器中 类似地LDR指令也通过上述方法读入一个32位的绝对数 在下例中 LDR指令将32位绝对数0 x11552634读入到r0寄存器中 用作调用routine1或者routine2的参数 67 32位地址送入一个寄存器中 续 voidload inti voidroutine1 int1 voidroutine2 int2 AREALOAD CODE READONLYIMPORTroutine1IMPORTroutine2EXPORTloadloadstmfdr13 r4 r14 ldrr4 routine1 首先将32位地址存放在附近的区域cmpsr0 1ldrner4 routine2ldrr0 0 x11552634 函数的第1个int参数bxr4ldmfdr13 r4 r14 bxr14 68 三 从IRQ和FIQ异常处理程序返回 从IRQ和FIQ异常处理程序返回时 返回地址应该是LR 4 有三种不同的编程方法 分别列出如下 返回方式1INT HANDLER SUBSPC LR 4 PC R14 4 69 从IRQ和FIQ异常处理程序返回 2 返回方式2INT HANDLERSUBR14 R14 4 R14 4 MOVSPC LR 70 从IRQ和FIQ异常处理程序返回 3 返回方式3INT HANDLERSUBR14 R14 4 R14 R14 4STMFDR13 R0 R3 R14 LDMFDR13 R0 R3 R15 71 四 循环结构 在ARM汇编中 没有专门的指令用来实现循环 一般通过跳转指令加条件码的形式来实现 可以采用比较指令CMP或者减法指令SUB等实现 参看下面的指令段 LOOPADDR4 R4 R0ADDR0 R0 1CMPR0 R1BLELOOP R0小于等于R1场合跳转在做完了两次加法操作后 比较R0 R1的值 影响条件标志 最后的条件跳转语句根据CMP指令执行的结果来决定是否进行循环 72 五 调用ARM汇编语言子程序 在ARM汇编语言中 子程序调用是通过BL指令完成的 BL指令的语法格式如下 BLsubname其中 subname是调用的子程序的名称 BL指令完成两个操作 将子程序的返回地址放在LR寄存器中 同时将PC寄存器值设置成目标子程序的第一条指令地址 在子程序返回时可以通过将LR寄存器的值传送到PC寄存器中来实现 子程序调用时通常使用寄存器R0 R3来传递参数和返回结果 73 调用汇编子程序举例 子程序DOADD完成加法运算 操作数放在R0和R1寄存器中 结果放在R0中 AREAEXAMPLE2 CODE READONLYENTRYstartMOVr0 10 R0设置输入参数MOVr1 3 R1设置输入参数BLdoadd 调用子程序doadd doaddADDr0 r0 r1 子程序实体 MOVpc lr 从子程序中返回END 74 六 高效率程序分支 设有C语言程序Intc switch inti switch i case0 returnmethod0 case1 returnmethod1 case2 returnmethod2 case3 returnmethod3 case4 returnmethod4 default returnmethod 可有汇编与之功能等价Arm swithcmpr0 5addltpc pc r0 lsl 2BmethodBmethod0Bmethod1Bmethod2Bmethod3Bmethod4 75 七 数据块复制示范程序 本程序将数据从源数据区复制到目标数据区复制时 以8个字为单位进行 对于最后所剩不足8个字的数据 以字为单位进行复制 这时程序跳转到copywords处执行 在进行以8个字为单位的数据复制时 保存了所用的8个工作寄存器 程序清单如下面所示 76 数据块复制示范程序 1 AREABlock CODE READONLY 设置段名称及属性numEQU20 设置将要复制的字数ENTRY 标识程序入口点StartLDRr0 src r0寄存器指向源数据区srcLDRr1 dst r1寄存器指向目标数据区dst 77 数据块复制示范程序 2 MOVr2 num r2指定将要复制的字数MOVsp 0 x400 设置数据栈指针 r13 用于保存工作寄存器数值blockcopy 进行以8个字为单位的数据复制MOVSr3 r2 LSR 3 需要进行的以8个字为单位的复制次数BEQcopywords 对于剩下不足8个字的数据 跳转到copywords 以字为单位复制STMFDsp r4 r11 保存工作寄存器 压栈octcopyLDMIAr0 r4 r11 从源数据区读取8个字的数据 放到8个寄存器中 并更新目标数据区指针r0STMIAr1 r4 r11 将这8个字数据写入到目标数据区中 并更新目标数据区指针r1SUBSr3 r3 1 将块复制次数减1BNEoctcopy 循环 直到完成以8个字为单位的块复制LDMFDsp r4 r11 恢复工作寄存器值 出栈 78 数据块复制示范程序 3 copywordsANDSr2 r2 7 剩下不足8个字的数据的字数BEQstop 数据复制完成wordcopyLDRr3 r0 4 从源数据区读取1个字的数据 放到r3寄存器中 并更新目标数据区指针r0 后索引偏移STRr3 r1 4 将这r3中数据写入到目标数据区中 并更新目标数据区指针r1 后索引偏移 79 数据块复制示范程序 4 SUBSr2 r2 l 将字数减1BNEwordcopy 循环 直到完成以字为单位的数据复制STOPAREABlockData DATA READWRITE 定义数据区BlockDatasrcDCD1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4dstDCD0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 定义源数据区src及目标数据区dstEND 结束汇编 80 课后练习1 请指出以下程序中的错误2 将以面的C分支程序改为功能相同的汇编程序 AREARRoutineA Code READONLYMOVR10 0XFF00SUB1MOVR6 100SEC MOVR8 0X200FloopMovR2 3BLoop Intc switch inti switch i case0 returnmethod0 case1 returnmethod1 case2 returnmethod2 default returnmethod 81 5 3ARM汇编 C和C 混合编程 在C C 程序中如果必须使用汇编指令来完成某些操作 可以采用两种方法 1 采用内嵌汇编 即在C C 源程序中嵌入一块汇编代码 让这块汇编代码来完成特定的操作 2 将必须使用汇编代码的部分独立编写成在一个文件中 形成一个子程序 C C 程序可以调用这些汇编程序来完成特定的操作 82 5 3 1内嵌汇编 内嵌汇编 inlineassembly 的语法如下 asm 指令 指令 注释 指令 83 内嵌汇编的指令用法 内嵌在C或者C 程序中的ARM汇编指令与普通 ADS 格式的ARM汇编指令有所不同 其主要原因在于C C 编译器在编译C C 源代码的同时要兼顾处理内嵌汇编程序 因此CPU的内部寄存器资源使用有额外约束 以下讲解内嵌ARM汇编指令的用法 84 ARM内嵌汇编程序的操作数 操作数内嵌汇编指令中作为操作数的寄存器和常量可以是表达式 这些表达式可以是char short或int类型 而且这些表达式都是作为无符号数进行操作 若需要带符号 用户需要自己处理与符号有关的操作 编译器将会计算这些表达式的值 并为其分配寄存器 85 ARM内嵌汇编程序的物理寄存器 物理寄存器内嵌汇编程序中使用物理寄存器有以下限制 不能直接向PC寄存器赋值 程序跳转只能使用B或BL指令实现不要使用过于复杂的C表达式 因为将会需要较多的物理寄存器 这将导致与其他指令中用到的物理寄存器产生使用冲突 编译器可能会使用R12或R13存放编译的中间结果 在计算表达式的值时可能会将寄存器R0 R3 R12和R14用于子程序调用 因此在内嵌的汇编指令中不要将这些寄存器同时指定为指令中的物理寄存器 通常内嵌的汇编指令中不要指定物理寄存器 因为这可能会影响编译器分配寄存器 进而影响代码的效率 86 其他内嵌汇编程序的编写注意点 常量 在内嵌汇编指令中 常量前面的 可以省略 指令展开 内嵌汇编指令中 如果包含常量操作数 该指令可能被内嵌汇编器展开成几条指令 标号 C程序中的标号可以被内嵌的汇编指令使用 但是只有指令B可以使用C程序中的标号 而指令BL则不能使用 内存单元的分配 所有的内存分配均由C编译器完成 分配的内存单元通过变量供内嵌汇编器使用 内嵌汇编器不支持内嵌程序中用于内存分配的伪指令 87 内嵌汇编程序中的SWI和BL指令 SWI和BL指令 在两个指令使用到内嵌汇编中 除了正常的操作数域外 还必须增加以下3个可选的寄存器列表 用于输入参数的寄存器列表 用于存储返回结果的寄存器列表 用于表示那些寄存器将有可能会被修改的寄存器列表 88 内嵌汇编代码举例字符串复制 1 includevoidstr cpy constchar src char dst intch asm loop 普通ARM汇编代码中的标号后面不能跟冒号 C程序中 的标号可以被内嵌的汇编指令使用 ARM内嵌汇编代码中 只有B指令可以使用C的标号 而BL指令不能够使用C代码 的标号 C程序的标号后面跟冒号 由Goto语句转向标号处 LDRBch src 1STRBch dst 1CMPch 0BNEloop 89 内嵌汇编代码举例字符串复制 2 intmain void constchar a Helloworld n charb 20 doinlineassemblyroutinestr cpy a b asm MOVR0 a 将串a的串首地址送到R0寄存器MOVR1 b 将串b的串首地址送到R1寄存器BLstr cpy R0 R1 调用C函数str cpy printf Originalstring s n a printf Copiedstring s n b 半主机方式显示复制前后的两个串return 0 90 5 3 2C C 程序与ARM汇编语言程序的相互调用 C C 程序与汇编程序相互调用时 应遵守相应的ATPCS 主要有五种调用 ARM汇编子程序调用C语言子程序ARM汇编子程序调用C 语言子程序C语言程序调用ARM汇编语言子程序C 语言程序调用ARM汇编语言子程序C语言程序调用C 语言子程序下面就每种具体情况逐一举例说明 91 C C 程序调用ARM汇编程序要点 设计汇编程序必须遵守ATPCS 保证程序调用时参数的正确传递 在汇编程序中使用EXPORT指示符声明本程序可以被别的程序调用 在C语言程序中使用extern关键词声明该汇编程序可以被调用 C 语言程序使用extern C 来声明该汇编程序可以被调用 92 例1C程序调用ARM汇编子程序 main 0522 csemihostingoutputmode includeexternintasmfile intarg1 intarg2 intarg3 intmain void inta1 1 a2 2 a3 4 printf ExampleofCProgramcallingAssemblyprogram n printf d d d 600 d n a1 a2 a3 asmfile a1 a2 a3 93 C程序调用ARM汇编子程序 续 ASM 0522 sEXPORTasmfileAREAMy pro CODE READONLYasmfileSTMFDSP R4 R6 R8 R7 addr0 r0 r1addr0 r0 r2movr4 600mulr3 r0 r4movr0 r3LDMFDSP R4 R6 R8 R7 movpc lrEND 94 例2ARM汇编程序调用C子程序 本案例程序比较两个IP地址的大小 a1 a4存放IP地址1的值 按照ATPCS传递参数 b1 b4存放IP地址2的值 通过栈传递参数 如果IP地址1的值大于IP地址2的值则返回1 如果IP地址1的值小于IP地址2的值则返回 1 如果两者相等则返回零 IP地址1取值 192 168 1 152 IP地址2取值 172 0 0 151 95 例2ARM汇编程序调用C子程序 续 C代码部分 includeexternintfunction void 声明function是外部函数 intcompare ip inta1 inta2 inta3 inta4 intb1 intb2 intb3 intb4 if a1 b1 returna1 b1 1 1 if a2 b2 returna2 b2 1 1 if a3 b3 returna3 b3 1 1 if a4 b4 returna4 b4 1 1 return0 intmain printf Thisisaexampleofsemihosting n printf resultis d n function 96 例2ARM汇编调用C子程序 续2 AREAFUNCTION CODE READONLY ARM汇编子程序IMPORTcompare ipEXPORTfunctionfunctionSTMFDr13 r0 r3 r14 保存寄存器到栈区MOVr3 0 x97 存入IP地址2的4个数 0 x97 151MOVr2 0 存入0MOVr1 0 存入0MOVr0 0 xac 存入0 xac 172STMIAr13 r0 r3 R0 R3覆盖存入栈区的R0 R3位置MOVr3 0 x98 存入IP地址1的4个数 0 x98 152MOVr2 1 存入1MOVr1 0 xa8 存入0 xa8 168MOVr0 0 xc0 存入0 xc0 192BLcompare ip 调用C语言函数进行IP值比较ADDr13 r13 0 x10 栈指针上移4个字 元素 LDRpc r13 4 将保存的r14值加载到PC 而后r13加4END 本段汇编代码的操作图解参看下一页 97 例2ARM汇编调用C子程序 续3 ARM汇编语言子程序Function的栈区操作图解 98 例3ARM汇编程序调用C 子程序 这是C 调用ARM汇编的范例程序 文件名 try C call S main函数位于这个 CPP文件extern C voidasmfunc void intmain void asmfunc 99 例3ARM汇编调用C 子程序 续 这个ARM汇编语言程序被main函数调用 该函数又调用ARM汇编函数cppfunc AREAmypro CODE READONLYIMPORTcppfuncEXPORTasmfuncasmfuncSTMFDsp lr BLcppfuncLDMFDsp pc END 100 例3ARM汇编调用C 子程序 续2 include includeusingnamespacestd constdoublePI 3 1415926 classpoint public point x 0 y 0 point doublea doubleb x a y b point point 101 例3ARM汇编调用C 子程序 续3 doubleGetX returnx doubleGetY returny point 102 例3ARM汇编调用C 子程序 续4 this x length cos a degree PI 180 this y length sin a degree PI 180 return this private doublex y 103 例3ARM汇编调用C 子程序 续5 extern C intcppfunc pointa 1 5 1 9 pointb 2 0 0 0 pointc 1 0 1 0 a Move b c Rotate 90 cout ais a GetX a GetY endl cout bis b GetX b GetY endl cout cis c GetX c GetY endl c
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 卫生院消防安全培训方案
- 地方电厂、分布电源继电保护专业培训课件
- 《师说》文言文知识总结高教版(2023)中职语文基础模块上册
- 医院科室排班表
- Module2-Grammar-公开课课件(一)
- 医疗机构医疗器械使用情况调研问卷
- 2025至2030年中国高级防冻液行业投资前景及策略咨询报告
- Module2-Listening-and-Vocabulary-公开课课件(一)
- 第八章 习题课 二面角的平面角的常见解法
- 中式快餐的消费者需求分析
- 两人股权分配协议书模板
- 2024至2030年中国中试基地行业发展形势及前景规划分析报告
- 儿科护理期末试卷及答案
- 安全伴我行-大学生安全教育智慧树知到期末考试答案章节答案2024年哈尔滨工程大学
- 江西省第一届职业技能大赛分赛场项目技术文件(世赛选拔)重型车辆维修
- CJ/T 28-2013 中餐燃气灶炒菜灶
- JJF 1064-2024坐标测量机校准规范
- 污水处理厂安全风险分级管控体系方案1
- 珠宝行业代卖合作协议书
- 北京市朝阳区2022-2023学年四年级下学期语文期末试卷(含答案)
- (MT654-2021)煤矿用带式输送机安全规范
评论
0/150
提交评论