惠州网站建设l优选蓝速科技,网站代码建设+实例,外国的html 素材网站,晋江网站建设公司哪家好为了使单独编译的c文件和汇编文件之间能够互相调用#xff0c;需要制定一系列的规则#xff0c;AAPCS就是ARM程序和Thumb程序中子程序调用的基本规则。
1、ATPCS概述 ATPCS规定了子程序调用过程中寄存器的使用规程、数据站的使用规则、参数的传递规则。为了适应一些特殊的需… 为了使单独编译的c文件和汇编文件之间能够互相调用需要制定一系列的规则AAPCS就是ARM程序和Thumb程序中子程序调用的基本规则。
1、ATPCS概述 ATPCS规定了子程序调用过程中寄存器的使用规程、数据站的使用规则、参数的传递规则。为了适应一些特殊的需求对这些规则进行改动可以得到几种不同的子程序调用规则具体包括 支持数据栈限制检查的ATPCS 支持只读段位置无关ROPI的ATPCS 支持可读写段位置无关(RWPI)的ATPCS 支持ARM程序和Thumb程序混合使用的ATPCS 处理浮点运算的ATPCS 相关调用程序必须遵守同一种ATPCS编译器/汇编器在ELF格式的目标文件中设置相应的属性标识用户选定 ATPSC类型。不同类型的ATPCS规则有对应的C语言库连接器根据用户的指定ATPCS类型链接相应的c库。 C语言的编译器编译的C子程序能够满足用户指定的ATPCS类型。而对于汇编语言需要用户来满足子程序间的ATPCS类型。汇编子程序必须满足如下三个条件 子程序编写时必须遵守相应的ATPCS规则 数据栈的使用要遵守相应的ATPCS规则 汇编器中使用-apcs选项 下面是keil中C语言配置的选项。 下面是汇编器的配置。 2、基本ATPCS
基本的ATPCS规则包括下面三个方面内容 各寄存器的使用规则及其相应的名称 数据栈的使用规则 参数传递的规则
满足基本类型的ATPCS程序运行速度更快占用内存更少但不支持以下功能 ARM程序和Thumb程序的互相调用注在Cortex-M3中使用的是Thumb2指令已经不区分ARM、Thumb指令了《Cortex-M3权威手册》对此有论述。因此该条存疑本文参考的资料也较老新版可能会更改待验证。。。。 数据以及代码的位置无关的支持 子程序的可重入性 数据栈检查的支持 派生的几种ATPCS规则是在基本的ATPCS基础上添加额外规则形成的目的就是提供上述功能。
2.1 寄存器的使用规则 寄存器的使用必须满足如下规则 子程序间通过R0--R3传递参数被调用的子程序在返回前无需恢复寄存器R0--R3的内容。 在子程序中使用R4--R11保存局部变量如果在子程序中使用到了寄存器R4--R11中的某些寄存器子程序进入前需要保存这些寄存器的值在返回时需要恢复。未用到不处理。在Thumb程序中通常只能使用寄存器R4--R7来保存局部变量。 寄存器R12用作子程序间scratch寄存器记作ip。在子程序间的连接代码段中常用这种使用规则。 寄存器R13用作数据栈指针记作sp。在子程序中sp不能用作其它用途进入子程序时的sp值和退出子程序时的sp值必须相等。 R14称为连接寄存器记作lr。用于保存子程序的返回地址如果在子程序中保存了返回地址R14可以用作其它的用途。 R15是程序计数器记作pc不能用于其它的用途。
ATPCS中各寄存器的使用规则及其名称
寄存器 别名特殊名称使用规则R15Pc程序计数器R14Lr连接寄存器R13Sp数据栈指针R12Ip子程序内部调用的scratch寄存器R11V8ARM状态局部变量寄存器8R10V7sl ARM状态局部变量寄存器7 在支持数据栈检查的ATPCS中为数据栈限制指针 R9V6sb ARM状态局部变量寄存器6 在支持RWPI的ATPCS中为静态基址寄存器 R8V5ARM状态局部变量寄存器5R7V4wr 局部变量寄存器4 Thumb状态工作寄存器 R6V3局部变量寄存器3R5V2局部变量寄存器2R4V1局部变量寄存器1R3A4参数/结果/scratch 寄存器4R2A3参数/结果/scratch 寄存器3R1A2参数/结果/scratch 寄存器2R0A1参数/结果/scratch 寄存器1
2.2 数据栈的使用规则 栈指针通常可以指向不同的位置。当栈指针指向栈顶元素即最后一个入栈的数据元素时称为FULL栈当栈指针指向与栈顶指针即最后一个入栈的数据元素相邻的一个可用数据单元时称为EMPTY栈。 栈的增长方式也可以不同向内存地址减小的方向增长时称为DESCENDING栈向地址增长的方向增长时称为ASCENDING栈。故有四种栈
FD FULL DESCENDINGED EMPTY DESCENDINGFA FULL ASCENDINGEA EMPTY ASCENDING ATPCS规定数据栈为FD栈并且数据栈的操作时8 Byte对齐。下面时数据栈的示例和名词解释。
数据栈栈指针stack pointer是指最后一个写入栈的数据的内存地址。数据栈的基地址stack base是指数据栈的最高地址。由于ATPCS中数据栈式FD类型实际上数据栈中最早入栈的数据占据的内存单元式基地址的下一个内存单元。数据栈界限stack limit是指数据栈可以使用的最低的内存单元的地址。已占用的数据栈used stack是指数据栈的基地址和数据栈栈指针之间的区域。其中包括数据栈栈指针对应的内存单元但不包括数据栈的基地址对应的内存单元。未占用的数据栈unused stack是指数据栈栈指针和数据栈界限之间的区域其中包括数据栈界限对应的内存单元但不包括数据栈栈指针对应的内存单元。数据栈中的数据帧stack frames是指在数据栈中为子程序分配的用来保存寄存器和局部变量的区域。 异常中断的处理程序可以使用被中断程序的数据栈这时用户要保证中断的程序的数据栈足够大。 数据栈的示意图 在ARMv5RE很老的版本了cortex-m3式ARMv7版本中批量传输指令LDRD/STRD要求的数据栈是8 Byte对齐以提高数据的传输速度。用ADS编译器产生的目标文件中外部接口的数据栈都是8 Byte对齐的并且编译器告诉连接器本目标文件的数据栈是8字节对齐的对于汇编程序来说如果目标文件中包含了外部调用则必须满足下列条件
外部接口的数据栈必须是8字节对齐保证在进入该汇编代码后知道该汇编代码调用外部程序之间数据栈的栈指针变化的是偶数个字如栈指针加2个字而非3个字。汇编程序中使用PRESERVE8位操作告诉连接器本汇编程序数据栈是8字节对齐的。
2.3 参数传递规则 根据参数个数是否固定可以将子程序分为参数个数固定的子程序和参数个数可变的子程序二者的参数传递规则不同。
2.3.1 参数个数可变的子程序参数传递规则少见对应C中的可变参数 当参数不超过4个时可以使用寄存器R0--R3来传递参数超过4个还可以使用数据栈来传递参数。 参数传递时将所有参数看作时存放在连续的内存字单元中的字数据然后依次将各字数据传送到寄存器R0--R3中如果大于4个将剩余的字数据传送到数据栈中入栈顺序与参数顺序相反。 按照上面的规则一个浮点数参数可以通过寄存器传递也可以通过数据栈传递也可能一半通过寄存器传递另一半通过数据栈传递。
2.3.2 参数不可变的子程序传递规则常见大部分C语言的情况 如果系统包含了浮点运算的硬件部件浮点参数将按照下面的规则传递
各个浮点参数按顺序处理为每个浮点参数分配FP寄存器分配的方法满足该浮点参数需要的且编号最小的一组连续FP寄存器 第一个整数参数通过R0--R3传输其余的参数按照数据栈传输。
2.3.3 子程序结果返回规则
子程序中结果返回的规则如下
结果为一个32位整数时可以通过R0返回.结果为一个64位整数时可以通过R0、R1返回以此类推。结果位一个浮点数时可以通过浮点运算部件的寄存器f0、d0或者s0返回结果为复合型的浮点数如复数时可以通过寄存器f0--fN或者d0--dN来返回。对于位数更多的结果需要通过内存来传递。
3 几种特定的ATPCS 几种特定的ATPCS是在基本的ATPCS基础上增加一些规则形成的 支持数据栈限制检查的ATPCS 支持只读段位置无关ROPI的ATPCS 支持可读写段位置无关(RWPI)的ATPCS 支持ARM程序和Thumb程序混合使用的ATPCS 处理浮点运算的ATPCS
3.1 支持数据栈限制检查的ATPCS 3.1.1 支持数据栈限制检查的ATPCS基本原理 如果在程序设计期间能够准确计算程序用到的内存大小就不需要进行数据栈检查但这在一般情况下很难做到这时就需要进行数据栈的检查。 在进行数据栈的检查时使用R10又记作sl作为数据栈限制指针。用户在程序中不能使用该寄存器。支持数据栈限制检查的ATPCS要满足下面的规则
在已占用的栈的最低地址和sl之间必须有256字节的空间。即sl所指的内存地址必须比已经占用的栈的最低地址低256字节。当中断处理程序可以使用用户的数据栈时在已经占用的栈的最低地址和sl之间除了必须保留的256字节的内存单元之外还必须为中断处理预留足够的内存空间。用户程序不能修改sl的值数据栈栈指针sp的值必须不小于sl的值
与支持数据栈限制检查的ATPCS相关的编译/汇编选项有下面几种
选项/swst(software stack limit checking)指示编译器生成的代码遵守支持数据栈限制检查的ATPCS。用户在程序设计期间不能准确计算出程序所需的所有数据栈大小时需要指定该选项。选项/noswst(no software stack limit checking)指示编译器生成的代码不支持数据栈限制检查功能。用户在程序设计期间能准确计算出程序所有的所有数据栈大小时可以指定该选项默认该选项。选项/swstna(software stack limit checking not applicable)如果汇编程序对于是否进行数据栈检查无所谓而与该汇编程序连续的其它程序指定了选项/swst或选项/noswst这时该汇编程序使用选项/swstna 3.1.2 编写遵守支持数据栈限制检查的ATPCS的汇编语言程序 对于C或者C来说如果在编译时指定swst选项生成的目标代码将遵守支持数据栈限制检查的ATPCS。 对于汇编程序来说如果要遵守支持数据栈限制检查的ATPCS用户在编写程序时必须满足支持数据栈限制检查的ATPCS所要求的规则。然后在汇编时指定选项swst。
3.2 支持只读段位置无关(ROPI)的ATPCS
3.2.1 支持只读段位置无关的ATPCS的应用场合 位置无关的只读段可能为位置无关的代码段也可能是只读数据段。使用 支持只读段位置无关的ATPCS可以避免必须将程序存放到特定的位置。常用于
程序在运行期间动态加载到内存中。程序在不同的场合与不同的程序组合后加载到内存中。在运行期间映射到不同的地址。在一些嵌入式系统中将程序放到ROM中运行时再加载到RAM中的不同地址Linux常用这种方式uboot加载Linux内核镜像文件到RAM中。
3.2.2 支持只读段位置无关的ATPCS的程序设计
如果程序遵守支持只读段位置无关的ATPCS需要满足如下规则
当ROPI段中的代码引用同一个ROPI段中的符号时必须是基于PC的。当ROPI段中的代码引用另一个ROPI段中的符号时必须是基于PC的。并且两个ROPI段的位置关系必须固定。其它被ROPI段中的代码引用的必须是绝对地址或基于sb的可写数据。ROPI段移动后对ROPI中符号的引用要作相应的调整。
3.3 支持可读写段位置无关(RWPI)的ATPCS 如果一个程序中所有的可读写段都是位置无关则称该程序遵守支持可读写段位置无关(RWPI)的ATPCS。使用支持可读写段位置无关的ATPCS可以避免必须将程序放到特定的位置。这时R9通常用作静态基址寄存器记作sb。可重入的子程序可以再内存中同时有多个实例各个实例拥有独立的可读写段。在生成一个新的实例时sb指向该实例的可读写段。RWPI段中的符号的计算方法为连接器首先计算出该符号相对于RWPI段中某一特定位置的偏移量通常该特定位置选为RWPI段的第一个字节处在程序运行时将该偏移量加上sb即可生成该符号的地址。
3.4 支持ARM程序和Thumb程序混合使用的ATPCS 据《Cortex-M3权威手册》中所述Cortex-M3已经不再区分ARM指令和Thumb指令M3中使用的时Thumb2指令集Thumb2指令集兼容32位和16位指令因此该部分在目前已经用不到就不再叙述。
3.5 处理浮点运算的ATPCS ATPCS支持VFP体系和FPA体系两种不同的浮点硬件体系和指令集两种体系对应的代码不兼容。 相应的ADS的编译器和汇编器有下面6种与浮点数相关的选项。
-fpu VFP-fpu FPA-fpu softVFP-fpu softVFP VFP-fpu softFPA-fpu none 当系统种包含浮点运算部件时可以选择上述选项。在M3内核种不包含浮点数运算单元但M4内核中包含一个可选的浮点数运算单元(FPU)FPU符合IEEE 754标准未实现完整的内容。FPU为单精度浮点单元浮点数据和计算基于IEEE Std 754-2008IEEE二进制浮点运算标准是VFP体系。
4 说明 本篇文章参考了《ARM体系结构与编程》杜春雷 著和《Cortex-M3权威指南》属于学习笔记性质。参考资料链接https://gitee.com/zichuanning520/htq_library