ATPCS:ARM-Thumb程序调用的基本规则

        为了使单独编译的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状态局部变量寄存器8
R10V7sl

ARM状态局部变量寄存器7

在支持数据栈检查的ATPCS中为数据栈限制指针

R9V6sb

ARM状态局部变量寄存器6

在支持RWPI的ATPCS中为静态基址寄存器

R8V5ARM状态局部变量寄存器5
R7V4wr

局部变量寄存器4

Thumb状态工作寄存器

R6V3局部变量寄存器3
R5V2局部变量寄存器2
R4V1局部变量寄存器1
R3A4参数/结果/scratch 寄存器4
R2A3参数/结果/scratch 寄存器3
R1A2参数/结果/scratch 寄存器2
R0A1参数/结果/scratch 寄存器1

2.2 数据栈的使用规则

        栈指针通常可以指向不同的位置。当栈指针指向栈顶元素(即最后一个入栈的数据元素)时,称为FULL栈;当栈指针指向与栈顶指针(即最后一个入栈的数据元素)相邻的一个可用数据单元时,称为EMPTY栈。

        栈的增长方式也可以不同,向内存地址减小的方向增长时,称为DESCENDING栈,向地址增长的方向增长时,称为ASCENDING栈。故,有四种栈:

  • FD FULL DESCENDING
  • ED EMPTY DESCENDING
  • FA FULL ASCENDING
  • EA 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-2008,IEEE二进制浮点运算标准,是VFP体系。

4 说明

        本篇文章参考了《ARM体系结构与编程》(杜春雷  著)和《Cortex-M3权威指南》,属于学习笔记性质。参考资料链接:https://gitee.com/zichuanning520/htq_library

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/167431.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

03、Python 字符串高级用法

目录 Python 字符串高级用法转义字符字符串格式化序列相关的方法大小写相关的方法dir 可以查看某个类的所有方法删除空白查找、替换相关方法 Python 字符串高级用法 转义字符 字符串格式化 序列相关的方法 字符串本质就是由多个字符组成,字符串的本质就是不可变序…

SpringBoot连接MySQL密码错误,报错:Access denied for user

记:一次连接MySQL报密码错误,Access denied for user 检查步骤: 核对用户和密码是否正确,用工具登陆试下。如果配置文件是yml格式,配置密码是123456这种纯数字,记得加上单/双引号。检查云上数据库配置&am…

基于PHP的创意设计分享系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

力扣每日一题59:螺旋矩阵||

题目描述: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]]示例 2: 输入&am…

【C语言小游戏--猜数字】

文章目录 前言1.游戏描述2.代码实现2.1打印菜单2.2构建基础框架2.3玩游戏2.3.1生成随机数2.3.1.1rand()2.3.1.2srand()2.3.1.3time() 2.3.2game() 2.4自己设定猜的次数 3.完整代码 前言 猜数字小游戏是我们大多数人学习C语言时都会了解到的一个有趣的C语言小游戏,下…

Javascript命令模式

Javascript命令模式 1 什么是命令模式2 命令模式的例子—菜单程序3 JavaScript 中的命令模式4 撤销命令5 宏命令 1 什么是命令模式 在一个餐厅中,当客人现场点餐或者打电话订餐时,老板会把客人的需求写在清单上,厨师会按照清单的顺序给客人炒…

驱动开发3 ioctl函数的使用+3个实例(不传递第三个参数、第三个参数为整型、第三个参数为地址)

开发板:stm32mp157aaa(Cortex-A7*2 Cortex-M4*1)开发环境:vscode、串口工具 1 引入ioctl函数的意义 linux操作系统中有意将数据的读写和读写功能的选择分别交给不同的函数去完成。就让read/write函数只进行数据的读写即可&#x…

多版本并发控制MVCC

什么是MVCC MVCC (Multiversion Concurrency Control),多版本并发控制。顾名思义,MVCC 是通过数据行的多个版本管理来实现数据库的并发控制。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之,…

SolidWorks模型导入到Gazebo中

首先建立好solidworks模型,然后另存为stl格式, 导出为STL文件时,文件名最好不要是中文,并且要将后缀STL改为stl,否则Gazebo无法识别 这是我创建好的机器人充电桩模型: 尺寸是单位是mm: 135mm …

【图像误差测量】测量 2 张图像之间的差异,并测量图像质量(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

图论06-【无权无向】-图的遍历并查集Union Find-力扣695为例

文章目录 1. 代码仓库2. 思路2.1 UF变量设计2.2 UF合并两个集合2.3 查找当前顶点的父节点 find(element) 3. 完整代码 1. 代码仓库 https://github.com/Chufeng-Jiang/Graph-Theory 2. 思路 2.1 UF变量设计 parent数组保存着每个节点所指向的父节点的索引,初始值为…

面向对象(基础)特征一:封装性(encapsulation)

文章目录 一、介绍(1)封装性(2)权限修饰符 二、案例(1)案例1 三、练习(1)练习1(2)练习2(3)练习3(4)练习4 面向…

数据丢失恢复怎么操作好?五种方法帮您恢复数据

丢失文件可能会造成灾难性的后果,因此您绝对需要最好的 PC 恢复软件。数据恢复软件必须快速、可靠并涵盖大多数文件格式。我们列表中最好的工具是一个甚至可以检索隐藏文件的解决方案。我们选择的另一个解决方案能够恢复700 多种独特的文件格式。 这种噩梦可能发生…

【PyTorch实战演练】自调整学习率实例应用(附代码)

目录 0. 前言 1. 自调整学习率的常用方法 1.1 ExponentialLR 指数衰减方法 1.2 CosineAnnealingLR 余弦退火方法 1.3 ChainedScheduler 链式方法 2. 实例说明 3. 结果说明 3.1 余弦退火法训练过程 3.2 指数衰减法训练过程 3.3 恒定学习率训练过程 3.4 结果解读 4. …

华为OD机试 - 代表团坐车 - 动态规划(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…

人工智能(5):深度学习简介

1 深度学习 —— 神经网络简介 深度学习(Deep Learning)(也称为深度结构学习【Deep Structured Learning】、层次学习【Hierarchical Learning】或者是深度机器学习【Deep Machine Learning】)是一类算法集合,是机器学…

Jenkins+Ant+Jmeter接口自动化集成测试

一、Jenkins安装配置 1、安装配置JDK1.6环境变量; 2、下载jenkins.war,放入C:\jenkins目录下,目录位置随意; Jenkins启动方法: cmd进入Jenkins目录下,执行java -jar jenkins.war 浏览器输入:l…

html5语义化标签

目录 前言 什么是语义化标签 常见的语义化标签 语义化的好处 前言 HTML5 的设计目的是为了在移动设备上支持多媒体。之前网页如果想嵌入视频音频,需要用到 flash ,但是苹果设备是不支持 flash 的,所以为了改变这一现状,html5 …

解决 Element-ui中 表格(Table)使用 v-if 条件控制列显隐时数据展示错乱的问题

本文 Element-ui 版本 2.x 问题 在 el-table-column 上需根据不同 v-if 条件来控制列显隐时&#xff0c;就会出现列数据展示错乱的情况&#xff08;要么 A 列的数据显示在 B 列上&#xff0c;或者后端返回有数据的但是显示的为空&#xff09;&#xff0c;如下所示。 <tem…

使用screen实现服务器代码一直运行

1.安装screen sudo apt install screen 2.创建一个screen&#xff08;创建一个名为chatglm的新的链接&#xff0c;用来一直运行 screen -S chatglm 3.查看进程列表 screen -ls 创建之后&#xff0c;就可以在当前窗口利用cd命令进入要执行的项目中&#xff0c;开始执行&#xf…