0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ATPCS基本规则

安芯教育科技 来源:极术社区 作者:Nuoeriris 2022-05-27 10:12 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

为了使单独编译的C语言程序和汇编程序之间能够相互调用,必须为子程序之间的调用规定一定的规则,ATPCS就是ARM程序和THUMB程序中子程序调用的基本规则。

1. ATPCS


ATPCS即ARM Thumb Procedure Call Standard(ARM-Thumb过程调用标准)的简称,ATPCS规定了一些调用和被调用程序之间调用的基本规则,这些基本规则包括子程序调用过程中寄存器的使用规则、数据栈的使用规则、参数的传递规则。为适应一些特定的需要,对这些基本的调用规则进行一些修改得到几种不同的子程序调用规则,这些特定的调用规则包括:

  • 支持数据栈限制检查的ATPCS

  • 支持只读段位置无关的ATPCS

  • 支持可读写段位置无关的ATPCS

  • 支持ARM程序和THUMB程序混合使用的ATPCS

有调用关系的所有子程序必须遵守同一种ATPCS,编译器或者汇编器在ELF格式的目标文件中设置相应的属性,标识用户选定的ATPCS类型。对应不同类型的ATPCS规则,有相应的C语言库,连接器根据用户指定的ATPCS类型连接相应的C语言库。使用ADS的C语言编译器编译的C语言子程序满足用户指定的ATPCS类型。而对于汇编语言程序来说,完全要依赖用户来保证各子程序满足选定的ATPCS类型。具体来说,汇编语言子程序必须满足下面三个条件:在子程序编写时必须遵守相应的ATPCS规则;数据栈的使用要遵守ATPCS规则;在汇编编译器中使用“--apcs”选项,使用“--apcs”选项并不影响代码的产生,编译器只是在各段中放置相应的属性,标识用户选定的属性。

2. ATPCS基本规则


基本ATPCS规定了在子程序调用时的一些基本规则,包括以下四个方面的内容:
  • 寄存器的使用规则及其相应的名字

  • 数据栈的使用规则

  • 参数传递的规则

  • 函数结果返回的规则

相对于其他类型的TPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少。但是它不能提供以下的支持:ARM程序和THUMB程序相互调用;数据以及代码的位置无关的支持;子程序的可重入性;数据栈检查的支持。而派生的其他几种特定的ATPCS就是在基本ATPCS的基础上再添加其他的规则而形成的 ,其目的就是提供上述的功能。
2.1 寄存器的使用规则
16f6f982-dd5a-11ec-ba43-dac502259ad0.png  前四个寄存器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可用作其它的用途。寄存器R15是程序计数器,记作PC;它不能用作其它用途。ATPCS中的各寄存器在ARM编译器和汇编器中都是预定义的。
2.2 数据栈的使用规则
栈指针通常可以指向不同的位置,当栈指针指向栈顶元素(即最后一个入栈的数据元素)时,称为Full栈。当栈指针指向与栈顶元素相邻的一个元素时,称为Empty栈。数据栈的增长方向也可以不同,当数据栈向内存减小的地址方向增长时,称为Descending栈。当数据栈向着内存地址增加的方向增长时,称为Ascending栈。综合这两种特点可以由以下4种数据栈:

	FD(FULL Descending):递增满栈 ED(Empty Descending):递增空栈 FA(FULL Ascending):递减满栈 EA(Empty Ascending):递减空栈 ATPCS规定数据栈为FD类型,并对数据栈的操作是8字节对齐的,下面是一个数据栈的示例及相关的名词:
  1. 数据栈栈指针,stack pointer指向最后一个写入栈的数据的内存地址。

  2. 数据栈的基地址,stack base是指数据栈的最高地址。由于ATPCS中的数据栈是FD类型的,实际上数据栈中最早入栈数据占据的内存单元是基地址的下一个内存单元。

  3. 数据栈界限,stack limit是指数据栈中可以使用的最低的内存单元地址。

  4. 已占用的数据栈,used stack是指数据栈的基地址和数据栈栈指针之间的区域,其中包括数据栈栈指针对应的内存单元。

  5. 数据栈中的数据帧(stack frames) 是指在数据栈中,为子程序分配的用来保存寄存器和局部变量的区域。

VAL(SP) <= stack base, VAL(SP) >= VAL(SL) >= stack limit + 256, VAL(LR) = return address

异常中断的处理程序可以使用被中断程序的数据栈,这时用户要保证中断的程序数据栈足够大。使用ADS编译器产生的目标代码中包含了DRFAT2格式的数据帧。在调试过程中,调试器可以使用这些数据帧来查看数据栈中的相关信息。而对于汇编语言来说,用户必须使用FRAME伪操作来描述数据栈中的数据帧。ARM汇编器根据这些伪操作在目标文件中产生相应的DRFAT2格式的数据帧。在ARMv5TE中,批量传送指令LDRD/STRD要求数据栈是8字节对齐的,以提高数据的传送速度。用ADS编译器产生的目标文件中,外部接口的数据栈都是8字节对齐的,并且编译器将告诉连接器:本目标文件中的数据栈是8字节对齐的。而对于汇编程序来说,如果目标文件中包含了外部调用,则必须满足以下条件:外部接口的数据栈一定是8位对齐的,也就是要保证在进入该汇编代码后,直到该汇编程序调用外部代码之间,数据栈的栈指针变化为偶数个字;在汇编程序中使用PRESERVE8伪操作告诉连接器,本汇编程序是8字节对齐的。17248938-dd5a-11ec-ba43-dac502259ad0.png
2.3 参数的传递规则
根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子程序。这两种子程序的参数传递规则是不同的。参数个数可变的子程序参数传递规则,对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3来进行参数传递,当参数超过4个时,还可以使用数据栈来传递参数。在参数传递时,将所有参数看做是存放在连续的内存单元中的字数据。然后,依次将各名字数据传送到寄存器R0,R1,R2,R3;如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递。参数个数固定的子程序参数传递规则,对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同,如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递:各个浮点参数按顺序处理;为每个浮点参数分配FP寄存器;分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器。第一个整数参数通过寄存器R0~R3来传递,其他参数通过数据栈传递。
2.4 子程序结果返回规则
  1. 结果为一个32位的整数时或小于32位的整数值以保留符号和符号的方式扩展为32位值的范围,可以通过寄存器R0返回。

  2. 结果为一个64位整数时,一个64位整数值被视为两个32位整数值,可以通过R0和R1返回,依此类推。

  3. 对于位数更多的结果,需要通过调用内存来传递,任何其它类型的值(例如结构化值)将转换为32位整数字序列,通过将其复制到连续的内存字中。

175d7626-dd5a-11ec-ba43-dac502259ad0.png  根据上面简单的测试可以看出:

	MOVS r2,#0x03 MOVS r1,#0x02 MOVS r0,#0x01 通过寄存器R0~R3来传递参数:

	ADDS r0,r3,r1 ADDS r0,r0,r2 通过寄存器R0返回。

3. 特定的ATPCS


3.1 支持数据栈限制检查的ATPCS

如果在程序设计期间能够准确地计算出程序所需的内存总量,就不需要进行数据栈的检查,但是在通常情况下这是很难做到的,这时需要进行数据栈的检查。在进行数据栈的检查时,使用寄存器R10作为数据栈限制指针,这时寄存器R10又记作SL。用户在程序中不能控制该寄存器。具体来说,支持数据栈限制的ATPCS要满足下面的规则:在已经占有的栈的最低地址和SL之间必须有256字节的空间,也就是说,SL所指的内存地址必须比已经占用的栈的最低地址低256个字节。当中断处理程序可以使用用户的数据栈时,在已经占用的栈的最低地址和SL之间除了必须保留的256个字节的内存单元外,还必须为中断处理预留足够的内存空间;用户在程序中不能修改SL的值;数据栈栈指针SP的值必须不小于SL的值。与支持数据栈限制检查的ATPCS相关的编译/汇编选项有下面几种:选项./ swst (编译过程中对输入文件使用堆栈检测)指示编译器生成的代码遵守支持数据栈限制检查的ATPCS,用户在程序设计期间不能够准确计算程序所需的数据栈大小时,需要指定该选项;选项./ noswst (编译过程中对输入文件不使用堆栈检测,这是编译器默认选项)指示编译器生成的代码不支持数据栈限制检查的功能,用户在程序设计期间能够准确计算出程序所需的数据栈大小,可以指定该选项;选项./ swst如果汇编程序对于是否进行数据栈检查无所谓,而与该汇编程序连接的其他程序指定了选项./ swst。对于256字节或更少的帧,可以按如下方式检查:

	CMP sp, sl BHS no_ovf BL |__16__rt_stkovf_split_small| no_ovf 对于大于 256 字节的帧,可以如下方式检查:

	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 DCD –Framesize 
3.2 编写遵守支持数据栈限制检查的ATPCS的汇编语言程序
对于C程序和C++程序来说,如果在编译时指定了选项./swst,生成的目标代码将遵守支持数据栈限制检查的ATPCS。对于汇编语言程序来说,如果要遵守支持数据栈限制检查的ATPCS,用户在编写程序时必须满足支持数据栈限制检查的ATPCS所要求的规则,然后指定选项./swst,下面介绍用户编写汇编语言程序时的一些要求。178aa7f4-dd5a-11ec-ba43-dac502259ad0.png
3.3 叶子子程序是指不调用别的程序的子程序
数据栈小于256字节的叶子子程序不许要进行数据栈检查,如果几个子程序组合起来构成的叶子子程序数据栈也小于256字节,这个规则同样适用;数据栈小于256字节的非叶子子程序可以使用下面的代码段来进行数据栈检查。ARM程序使用:

	SUB sp,sp,#size ; #size 为sp和sl之间必须保留的空间大小 CMP sp,sl; BLLO _ARM_stack_overflow THUMB程序使用:

	ADD sp,#-size ; #size为sp和sl之间必须保留的空间大小 CMP sp,sl; BLLO _THUMB_stack_overflow 数据栈大于256字节的子程序,为了保证SP的值不小于数据栈可用的内存单元最小的地址值,需要引入相应的寄存器。在使用超过 256 字节堆栈空间的例程中检查溢出更为复杂,不能简单地从SP减去帧大小。在这种情况下,必须使用如下序列向限制检查代码建议SP的新值:ARM程序使用下列代码:

	SUB ip,sp,#size; CMP ip,sl; BLLO _ARM_stack_overflow THUMB程序使用下列代码:

	LDR wr,#-size; ADD wr,sp; CMP wr,sl; BLLO _THUMB_stack_overflow 在编译或汇编时,/interwork (指定输入文件符合ARM/Thumb交互标准)告诉编译器或汇编器生成的目标代码遵守支持ARM-THUMB的ATPCS,它用在以下场合:
  • 程序中存在ARM程序调用THUMB程序的情况

  • 程序中存在THUMB程序调用ARM程序的情况

  • 需要连接器来进行ARM状态和THUMB状态切换的情况

在下述情况下使用选项/nointerwork:程序中不包含THUMB程序;用户自己进行ARM程序和THUMB程序切换。需要注意的是:在同一个C/C++程序中不能同时有ARM指令和THUMB指令。17b3d426-dd5a-11ec-ba43-dac502259ad0.png  \_\_asm 关键字用于调用内联汇编程序,可以用在C或C++源码中内嵌汇编语言,如下所示:17e3495e-dd5a-11ec-ba43-dac502259ad0.png  ATPCS规则就是定义了函数传参以及返回数据的标准,定义了寄存器在函数调用时的作用。

						

						

						

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144666
  • 函数
    +关注

    关注

    3

    文章

    4406

    浏览量

    66863
  • 系统控制
    +关注

    关注

    0

    文章

    34

    浏览量

    16510

原文标题:技术分享 | Cortex-M0中断控制和系统控制(七)

文章出处:【微信号:Ithingedu,微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Altair PollEx:PCB规则检查及系统EMC仿真技术

    Altair PollEx:PCB规则检查及系统EMC仿真技术
    的头像 发表于 09-17 11:19 5025次阅读
    Altair PollEx:PCB<b class='flag-5'>规则</b>检查及系统EMC仿真技术

    Jtti防火墙规则配置指南:从入门到精通的全面解析

    在网络安全日益重要的今天,防火墙作为企业网络的第一道防线,其规则配置直接决定了防护效果。本文将深入解析防火墙规则配置的核心要点,从基础概念到高级策略,帮助您构建既安全又高效的网络防护体系。我们将重点
    的头像 发表于 08-25 14:44 357次阅读

    厚声电阻标签的命名规则

    厚声电阻标签的命名规则围绕尺寸、功率、精度、阻值及包装等核心参数展开,采用结构化编码体系确保信息清晰传递。以下是具体规则解析: 一、尺寸编码:英制与公制对照 厚声电阻采用英制尺寸标注,对应公制封装
    的头像 发表于 07-28 17:24 904次阅读
    厚声电阻标签的命名<b class='flag-5'>规则</b>

    渝林智造 | 守护林海!地表火探测器如何改写森林防火规则

    渝林智造 | 守护林海!地表火探测器如何改写森林防火规则
    的头像 发表于 07-17 17:45 834次阅读
    渝林智造 | 守护林海!地表火探测器如何改写森林防火<b class='flag-5'>规则</b>?

    方案分享 | ARXML 规则下 ECU 总线通讯与 ADTF 测试方案

    汽车电子开发新进展:ARXML 规则与 ADTF 框架结合,实现 ECU 总线通讯高效测试
    的头像 发表于 06-25 09:53 2863次阅读
    方案分享 | ARXML <b class='flag-5'>规则</b>下 ECU 总线通讯与 ADTF 测试方案

    KiCad 中的自定义规则(KiCon 演讲)

    “  Seth Hillbrand 在 KiCon US 2025 上为大家介绍了 KiCad 的规则系统,并详细讲解了自定义规则的设计与实例。  ”   演讲主要围绕 加强 KiCad 中的自定义
    的头像 发表于 06-16 11:17 1508次阅读
    KiCad 中的自定义<b class='flag-5'>规则</b>(KiCon 演讲)

    时源芯微 PCB 布线规则详解

    PCB 布线规则详解 走线方向控制规则 相邻布线层的走线方向应采用正交结构,避免不同信号线在相邻层沿同一方向走线,以此降低不必要的层间串扰。若因 PCB 板结构限制(例如部分背板)难以避免该情况
    的头像 发表于 05-20 16:28 683次阅读

    旺诠合金电阻的命名规则

    旺诠合金电阻的命名规则相对严谨且包含丰富的信息,通常包括电阻值、精度、温度系数和功率等级等关键参数。以下是对旺诠合金电阻命名规则的详细解读: 一、电阻值 电阻值是电阻本身的物理特性,通常以欧姆
    的头像 发表于 05-20 11:22 488次阅读
    旺诠合金电阻的命名<b class='flag-5'>规则</b>

    Altium Designer中PCB设计规则设置

    在使用 Altium Designer 进行PCB设计时,除了电气间距(Clearance)等基础规则外, 导线宽度、阻焊层、内电层连接、铜皮敷设等规则也同样重要 。这些设置不仅影响布线效率,还决定了成品板的可制造性与可靠性。
    的头像 发表于 04-17 13:54 7150次阅读
    Altium Designer中PCB设计<b class='flag-5'>规则</b>设置

    如何在特定区域设置线宽、线距规则

    “  今天偷个懒,分享一个 Hayden 大佬提供的自定义规则,非常实用。可以在特定区域(如BGA器件范围内)定义特殊的线宽、线距规则。  ” 就是下面这段自定义规则,表示 U10
    的头像 发表于 03-19 11:20 1062次阅读
    如何在特定区域设置线宽、线距<b class='flag-5'>规则</b>

    STTH8S06D命名规则是什么?

    STTH8S06D命名规则
    发表于 03-13 06:11

    芯片设计中的设计规则检查

    设计规则检查(Design Rule Check,简称DRC)是芯片设计中的一个关键步骤,旨在确保电路设计的物理布局符合制造工艺的要求。可以把它类比为建筑设计中的检查流程,确保建筑图纸中的所有尺寸
    的头像 发表于 03-04 14:58 1340次阅读

    高速信号线走线规则有哪些

    在高速数字电路设计中,信号完整性(SI)是确保系统性能和可靠性的核心要素。高速信号线的走线规则对于维持信号质量、减少噪声干扰以及优化时序性能至关重要。本文将深入探讨高速信号线走线的关键规则,旨在为工程师提供全面的设计指导和实践建议。
    的头像 发表于 01-30 16:02 2313次阅读

    电子线路信号完整性设计规则

    电子发烧友网站提供《电子线路信号完整性设计规则.pdf》资料免费下载
    发表于 01-21 09:24 0次下载
    电子线路信号完整性设计<b class='flag-5'>规则</b>

    和Dr Peter一起学KiCad 4.8:设计规则检查(DRC)

    和Dr Peter一起学KiCad 4.8:设计规则检查(DRC)
    的头像 发表于 12-25 14:55 2836次阅读
    和Dr Peter一起学KiCad 4.8:设计<b class='flag-5'>规则</b>检查(DRC)