黑色羽翼葵程序之间能够相互调用,必须为子程序之间的调用规定一定的规则,ATPCS就是
ATPCS即ARM Thumb Procedure Call Standard(ARM-Thumb过程调用标准)的简称,ATPCS规定了一些调用和被调用程序之间调用的基本规则,这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则、参数的传递规则。为适应一些特定的需要,对这些基本的调用规则进行一些修改得到几种不同的子程序调用规则,这些特定的调用规则包括:
有调用关系的所有子程序必须遵守同一种ATPCS,编译器或者汇编器在ELF格式的目标文件中设置相应的属性,标识用户选定的ATPCS类型。对应不同类型的ATPCS规则,有相应的C语言库,连接器根据用户指定的ATPCS类型连接相应的C语言库。
S的C语言编译器编译的C语言子程序满足用户指定的ATPCS类型。而对于汇编语言程序来说,完全要依赖用户来保证各子程序满足选定的ATPCS类型。具体来说,汇编语言子程序必须满足下面三个条件:在子程序编写时必须遵守相应的ATPCS规则;数据栈的使用要遵守ATPCS规则;在汇编编译器中使用“--apcs”选项,使用“--apcs”选项并不影响代码的产生,编译器只是在各段中放置相应的属性,标识用户选定的属性。
相对于其他类型的TPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少。但是它不能提供以下的支持:ARM程序和THUMB程序相互调用;数据以及代码的位置无关的支持;子程序的可重入性;数据栈检查的支持。而派生的其他几种特定的ATPCS就是在基本ATPCS的基础上再添加其他的规则而形成的 ,其目的就是提供上述的功能。
前四个寄存器R0~R3用于将参数值传递到例程中并将结果值传递出例程,并在例程中保存中间值(但通常仅在子例程调用之间),子程序通过寄存器R0~R3来传递参数,这时寄存器可以记作:A1~A4,被调用的子程序在返回前无需恢复寄存器R0~R3的内容。
在子程序中,使用R4~R11来保存局部变量,这时寄存器R4~R11可以记作:V1~V8 。如果在子程序中使用到V1~V8的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值,对于子程序中没有用到的寄存器则不必执行这些操作。在THUMB程序中,通常只能使用寄存器R4~R7来保存局部变量。
寄存器R12用作子程序间暂存寄存器,记作IP;在子程序的连接代码段中经常会有这种使用规则。
寄存器R13用作数据栈指针,记做SP,在子程序中寄存器R13不能用做其他用途。寄存器SP在进入子程序时的值和退出子程序时的值必须相等。
寄存器R14用作连接寄存器,记作LR;它用于保存子程序的返回地址,如果在子程序中保存了返回地址,则R14可用作其它的用途。
栈指针通常可以指向不同的位置,当栈指针指向栈顶元素(即最后一个入栈的数据元素)时,称为Full栈。当栈指针指向与栈顶元素相邻的一个元素时,称为Empty栈。数据栈的增长方向也可以不同,当数据栈向内存减小的地址方向增长时,称为Descending栈。当数据栈向着内存地址增加的方向增长时,称为Ascending栈。
FD(FULL Descending):递增满栈 ED(Empty Descending):递增空栈 FA(FULL Ascending):递减满栈 EA(Empty Ascending):递减空栈
ATPCS规定数据栈为FD类型,并对数据栈的操作是8字节对齐的,下面是一个数据栈的示例及相关的名词:
数据栈栈指针,stack pointer指向最后一个写入栈的数据的内存地址。
数据栈的基地址,stack base是指数据栈的最高地址。由于ATPCS中的数据栈是FD类型的,实际上数据栈中最早入栈数据占据的内存单元是基地址的下一个内存单元。
数据栈界限,stack limit是指数据栈中可以使用的最低的内存单元地址。
已占用的数据栈,used stack是指数据栈的基地址和数据栈栈指针之间的区域,其中包括数据栈栈指针对应的内存单元。
数据栈中的数据帧(stack frames) 是指在数据栈中,为子程序分配的用来保存寄存器和局部变量的区域。
异常中断的处理程序可以使用被中断程序的数据栈,这时用户要保证中断的程序数据栈足够大。使用ADS编译器产生的目标代码中包含了DRFAT2格式的数据帧。在调试过程中,调试器可以使用这些数据帧来查看数据栈中的相关信息。而对于汇编语言来说,用户必须使用FRAME伪操作来描述数据栈中的数据帧。ARM汇编器根据这些伪操作在目标文件中产生相应的DRFAT2格式的数据帧。
中,批量传送指令LDRD/STRD要求数据栈是8字节对齐的,以提高数据的传送速度。用ADS编译器产生的目标文件中,外部接口的数据栈都是8字节对齐的,并且编译器将告诉连接器:本目标文件中的数据栈是8字节对齐的。而对于汇编程序来说,如果目标文件中包含了外部调用,则必须满足以下条件:外部接口的数据栈一定是8位对齐的,也就是要保证在进入该汇编代码后,直到该汇编程序调用外部代码之间,数据栈的栈指针变化为偶数个字;在汇编程序中使用PRESERVE8伪操作告诉连接器,本汇编程序是8字节对齐的。
根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子程序。这两种子程序的参数传递规则是不同的。
参数个数可变的子程序参数传递规则,对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3来进行参数传递,当参数超过4个时,还可以使用数据栈来传递参数。在参数传递时,将所有参数看做是存放在连续的内存单元中的字数据。然后,依次将各名字数据传送到寄存器R0,R1,R2,R3;如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递。
参数个数固定的子程序参数传递规则,对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同,如果系统包含浮点运算的
部件,浮点参数将按照下面的规则传递:各个浮点参数按顺序处理;为每个浮点参数分配FP寄存器;分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器。第一个整数参数通过寄存器R0~R3来传递,其他参数通过数据栈传递。
结果为一个32位的整数时或小于32位的整数值以保留符号和符号的方式扩展为32位值的范围,可以通过寄存器R0返回。
结果为一个64位整数时,一个64位整数值被视为两个32位整数值,可以通过R0和R1返回,依此类推。
对于位数更多的结果,需要通过调用内存来传递,任何其它类型的值(例如结构化值)将转换为32位整数字序列,通过将其复制到连续的内存字中。
如果在程序设计期间能够准确地计算出程序所需的内存总量,就不需要进行数据栈的检查,但是在通常情况下这是很难做到的,这时需要进行数据栈的检查。在进行数据栈的检查时,使用寄存器R10作为数据栈限制指针,这时寄存器R10又记作SL。用户在程序中不能控制该寄存器。具体来说,支持数据栈限制的ATPCS要满足下面的规则:在已经占有的栈的最低地址和SL之间必须有256字节的空间,也就是说,SL所指的内存地址必须比已经占用的栈的最低地址低256个字节。当中断处理程序可以使用用户的数据栈时,在已经占用的栈的最低地址和SL之间除了必须保留的256个字节的内存单元外,还必须为中断处理预留足够的内存空间;用户在程序中不能修改SL的值;数据栈栈指针SP的值必须不小于SL的值。
与支持数据栈限制检查的ATPCS相关的编译/汇编选项有下面几种:选项./ swst (编译过程中对输入文件使用堆栈
)指示编译器生成的代码遵守支持数据栈限制检查的ATPCS,用户在程序设计期间不能够准确计算程序所需的数据栈大小时,需要指定该选项;选项./ noswst (编译过程中对输入文件不使用堆栈检测,这是编译器默认选项)指示编译器生成的代码不支持数据栈限制检查的功能,用户在程序设计期间能够准确计算出程序所需的数据栈大小,可以指定该选项;选项./ swst如果汇编程序对于是否进行数据栈检查无所谓,而与该汇编程序连接的其他程序指定了选项./ swst。
CMP sp, sl BHS no_ovf BL __16__rt_stkovf_split_small no_ovf
LDR wr, framesize ADD wr, sp CMP wr, sl BHS no_ovf BL __16__rt_stkovf_split_big no_ovf MOV sp,wr ; ... ALIGN Framesize
程序来说,如果在编译时指定了选项./swst,生成的目标代码将遵守支持数据栈限制检查的ATPCS。对于汇编语言程序来说,如果要遵守支持数据栈限制检查的ATPCS,用户在编写程序时必须满足支持数据栈限制检查的ATPCS所要求的规则,然后指定选项./swst,下面介绍用户编写汇编语言程序时的一些要求。
数据栈小于256字节的叶子子程序不许要进行数据栈检查,如果几个子程序组合起来构成的叶子子程序数据栈也小于256字节,这个规则同样适用;数据栈小于256字节的非叶子子程序可以使用下面的代码段来进行数据栈检查。
SUB sp,sp,#size ; #size 为sp和sl之间必须保留的空间大小 CMP sp,sl; BLLO _ARM_stack_overflow
ADD sp,#-size ; #size为sp和sl之间必须保留的空间大小 CMP sp,sl; BLLO _THUMB_stack_overflow
数据栈大于256字节的子程序,为了保证SP的值不小于数据栈可用的内存单元最小的地址值,需要引入相应的寄存器。在使用超过 256 字节堆栈空间的例程中检查溢出更为复杂,不能简单地从SP减去帧大小。
SUB ip,sp,#size; CMP ip,sl; BLLO _ARM_stack_overflow
LDR wr,#-size; ADD wr,sp; CMP wr,sl; BLLO _THUMB_stack_overflow
在编译或汇编时,/interwork (指定输入文件符合ARM/Thumb交互标准)告诉编译器或汇编器生成的目标代码遵守支持ARM-THUMB的ATPCS,它用在以下场合:
在下述情况下使用选项/nointerwork:程序中不包含THUMB程序;用户自己进行ARM程序和THUMB程序切换。需要注意的是:在同一个C/C++程序中不能同时有ARM指令和THUMB指令。
\_\_asm 关键字用于调用内联汇编程序,可以用在C或C++源码中内嵌汇编语言,如下所示:
ATPCS规则就是定义了函数传参以及返回数据的标准,定义了寄存器在函数调用时的作用。
,对快速分辨型号差异有很大的帮助,本文重点介绍一下SiC器件的命名详细
介绍 /
布线是 PCB 设计的重要组成部分,也是整个 PCB 设计中工作量最大和最耗时间的部分,工程师在进行 PCB 布线工作时,需要遵循一些基本的
:遵照“先大后小,先难后易”的布置原则,即重要的单元电路、核心元器件应当优先布局。
,所以要了解PCB设计流程非常重要,可以建立清晰的设计思路,随时平衡和变化策略以应对复杂的设计。
为了使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序之间的调用规定一定的
的单位跟随画布属性里设置的单位,此处单位是mil。导线mil;不同网络元素之间最小间距为8mil;孔外径为24mil,孔内径为12mil;线
就是设计要求。如果我们在设计PCB时没有按照这些设计要求来进行PCB板的布局布线时,最后我们设计完成的PCB板是使用不了的。所以PCB的布局布线
非常非常重要,它能指导我们设计完成能够满足要求的并正常工作的PCB板。...
! /
灵动微课堂 (第181讲) Cortex-M0中断控制和系统控制(七)
为了使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序之间的调用规定一定的
可以到相应芯片的datasheet里面查找,datasheet可以从TI的官网上面查找相应的芯片,然后找到对应的芯片的datasheet。下面的这个图是针对TMS320C66X系列
打开altium designer软件,在设置DesignRooms根据自己的要求
本文档的主要内容详细介绍的是Altium Designer教程之PCB的设计
体现了一种模块化设计的思想,其基本内容是C模块(函数)和汇编模块(函数)相互调用的一套
)。我感觉比在线汇编功能强大(不用有很多忌讳),条理更清楚(很简单的几条
规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。
检查?比如说线宽,焊盘间的距离,线与线之间的间距,焊盘与线之间的间距怎样定义设置?
manufacturing-minimum solder masker silver下添加两条
,为什么第二条针对mcu单个器件的无效,只检查第一条。如果我想要第二条是U0:mcu引脚间距设为4mil有效应该怎么设
的Apriori 算法的基础上,为了提高用户数据挖掘的人机交互性能,解决关联
,LAYOUT PCB应该会比较好,不管是高速还是低频电路,都基本如此。
Arm Mobile Studio 2022.4实现自动性能监控等功能
科达嘉大电流数字功放电感CPD2320S、3119SA系列:宽频宽温、低损耗、高线性度
上拉式#嵌入式开发 #电路设计 #造物大赏 #电子元器件 #电子制作 磁悬浮
|