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.mzph.cn/news/115782.shtml

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

相关文章

【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 )

文章目录 一、继承 组合 模式的类对象 构造函数和析构函数调用规则1、场景说明2、调用规则 二、完整代码示例分析1、代码分析2、代码示例 一、继承 组合 模式的类对象 构造函数和析构函数调用规则 1、场景说明 如果一个类 既 继承了 基类 ,又 在类中 维护了一个 其它类型 的…

腾讯地图基本使用(撒点位,点位点击,弹框等...功能) 搭配Vue3

腾讯地图的基础注册账号 展示地图等基础功能在专栏的上一篇内容 大家有兴趣可以去看一看 今天说的是腾讯地图的在稍微一点的基础操作 话不多说 直接上代码 var marker ref(null) var map var center ref(null) // 地图初始化 const initMap () > {//定义地图中心点坐标…

Mysql数据库 3.SQL语言 DML数据操纵语言 增删改

DML语句:用于完成对数据表中数据的插入、删除、修改操作 一.表数据插入 插入数据语法: 步骤例: 1.声明数据库:use 数据库名; 2.删除操作:drop table if exists 表名; 3.创建数据库中的表:create table 表…

Java,回形数

回形数基本思路: 用不同的四个分支分别表示向右向下向左向上,假如i表示数组的行数,j表示数组的列数,向右向左就是控制j的加减,向上向下就是控制i的加减。 class exercise {public static void main(String[] args){//回…

【AOA-VMD-LSTM分类故障诊断】基于阿基米德算法AOA优化变分模态分解VMD的长短期记忆网络LSTM分类算法(Matlab代码)

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

Node学习笔记之fs模块

fs 全称为 file system ,称之为 文件系统 ,是 Node.js 中的 内置模块 ,可以对计算机中的磁盘进行操 作。 本章节会介绍如下几个操作: 文件写入文件读取文件移动与重命名文件删除文件夹操作查看资源状态 一、文件写入 文件写入就…

CAPL如何实现27服务解锁

在文章《CANoe-如何实现27服务解锁》里,我们介绍了诊断控制台中如何实现27解锁,如果我想在CANoe中使用CAPL程序解锁的话,又要如何实现呢? CAPL脚本也是通过模拟手动操作来实现27解锁,所以步骤为: 发送10 03发送27 01接收67 01,获取seed值根据seed值和算法,计算出key值…

http post协议实现简单的rpc协议,WireShark抓包分析

文章目录 1.http 客户端-RPC客户端1.http 服务端-RPC服务端3.WireShark抓包分析3.1客户端到服务端的HTTP/JSON报文3.2服务端到客户端的HTTP/JSON报文 1.http 客户端-RPC客户端 import json import requests# 定义 RPC 客户端类 class RPCClient:def __init__(self, server_url…

ZYNQ linux调试LCD7789

一,硬件管脚 1,参数解释和实物 LVGL是一个开源的图形库,主要用于MCU上屏幕UI的部署,功能完善,封装合理,可裁切性强,也可以实现Linux上fbx的部署。LVGL官网LVGL - Light and Versatile Embedded Graphics Library 每根线的作用

接口测试 Jmeter 接口测试 —— 请求 Headers 与传参方式

一、 背景: 在使用 Jmeter 进行接口测试时,有些小伙伴不知道 Headers 和请求参数 (Parameters,Body Data) 的联系,本文主要讲 Content-Type 为 application/x-www-form-urlencoded 和 application/json 的场景。 1、使用 Parame…

[SWPUCTF 2023 秋季新生赛] web题解

文章目录 colorful_snakeNSS_HTTP_CHEKER一键连接!ez_talkPingpingpingUnS3rialize查查needIf_elseRCE-PLUSbackup colorful_snake 打开题目,查看js源码 直接搜flag 把那三行代码复制到控制器,得到flag NSS_HTTP_CHEKER 都是http请求基本知识 抓包按照…

如何保养维护实验室超声波清洗机

实验室是用于各个行业产品的研发以及检验的场所,所以对其中所使用的各种物品都有着极高的要求,因此只有品类齐全的实验室超声波清洗机能够满足实验室对于清洁以及其他方面的一些需求,但是要想实验室超声波清洗机设备的性能能够始终如一&#…

驱动开发day4

通过字符设备驱动的分步实现编写LED驱动,另外实现设备文件和驱动的绑定 head.h #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }…

RHCE---Shell基础 2

文章目录 目录 文章目录 前言 一.变量 概述 定义 自定义变量 环境变量 概述: 定义环境变量: 位置变量 "$*"会把所有位置参数当成一个整体(或者说当成一个单词 变量的赋值和作用域 read 命令 变量和引号 变量的作用域 变…

【茫茫架构路】1. Class File字节码文件解析

本文所有内容的JDK版本为 OpenJDK 11 JDK11 Class File官方说明。 Java解析字节码文件源码参考,以下为部分字节码解析源码展示。 public ClassFile(DataInputStream in) {try {//magic: 0xCAFEBABEthis.magic ClassReader.readInt(in);System.out.println("m…

高等数学啃书汇总重难点(五)定积分

最近都在忙着刷题,尤其是政治和英语也开始加量复习了,该系列断更了将近2个月~不过最近在刷题的时候又遇到一些瓶颈,因此回归基础来整理一下知史点~ 总的来说,虽然第五章也是重中之重,定理数量也很多,但&…

C语言每日一题(17)老人的数目

力扣 2678 老人的数目 给你一个下标从 0 开始的字符串 details 。details 中每个元素都是一位乘客的信息,信息用长度为 15 的字符串表示,表示方式如下: 前十个字符是乘客的手机号码。接下来的一个字符是乘客的性别。接下来两个字符是乘客的…

JMeter添加插件

一、前言 ​ 在我们的工作中,我们可以利用一些插件来帮助我们更好的进行性能测试。今天我们来介绍下Jmeter怎么添加插件? 二、插件管理器 ​ 首先我们需要下载插件管理器jar包 下载地址:Install :: JMeter-Plugins.org 然后我们将下载下来…

MYSQL(事务+锁+MVCC+SQL执行流程)理解

一)事务的特性: 一致性:主要是在数据层面来说,不能说执行扣减库存的操作的时候用户订单数据却没有生成 原子性:主要是在操作层面来说,要么操作完成,要么操作全部回滚; 隔离性:是自己的事务操作自己的数据,不会受到到其…

Centos 7 Zabbix配置安装

前言 Zabbix是一款开源的网络监控和管理软件,具有高度的可扩展性和灵活性。它可以监控各种网络设备、服务器、虚拟机以及应用程序等,收集并分析性能指标,并发送警报和报告。Zabbix具有以下特点: 1. 支持多种监控方式:可…