嵌入式C和汇编混合编程规则——ATPCS规则

2024-05-19 10:32

本文主要是介绍嵌入式C和汇编混合编程规则——ATPCS规则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ATPCS规则

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

.ATPCS概述

ATPCS规定了一些子程序之间调用的基本规则.这些基本规则包括子程序调用过程中寄存器的使用规则,数据栈的使用规则,参数的传递规则.为适应一些特定的需要,对这些基本的调用规则进行一些修改得到几种不同的子程序调用规则,这些特定的调用规则包括:

Ø  支持数据栈限制检查的ATPCS.

Ø  支持只读段位置无关的ATPCS.

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

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

Ø  处理浮点运算的ATPCS

 有调用关系的所有子程序必须遵守同一种ATPCS. 编译器或者汇编器在ELF格式的目标文件中设置相应的属性,标识用户选定的ATPCS类型.对应不同类型的ATPCS规则,有相应的C语言库,连接器根据用户指定的ATPCS类型连接相应的C语言库。

 使用ADSC语言编译器编译的C语言子程序满足用户指定的ATPCS类型. 而对于汇编语言程序来说,完全要依赖用户来保证各子程序满足选定的ATPCS类型. 具体来说,汇编语言子程序必须满足下面三个条件:

Ø  在子程序编写时必须遵守相应的ATPCS规则;

Ø  数据栈的使用要遵守ATPCS规则;

Ø  在汇编编译器中使用-apcs选项

. 基本ATPCS...

基本ATPCS规定了在子程序调用时的一些基本规则,包括以下三个方面的内容:

Ø  各寄存器的使用规则及其相应的名字;

Ø  数据栈的使用规则;

Ø  参数传递的规则.

相对于其他类型的ATPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少. 但是它不能提供以下的支持: ARM程序和THUMB程序相互调用; 数据以及代码的位置无关的支持; 子程序的可重入性; 数据栈检查的支持. 而派生的其他几种特定的ATPCS就是在基本ATPCS的基础上再添加其他的规则而形成的.其目的就是提供上述的功能...

寄存器的使用规则:

1. 子程序通过寄存器R0-R3来传递参数. 这时寄存器可以记作: A1-A4 , 被调用的子程序在返回前无需恢复寄存器R0-R3的内容.

2. 在子程序中,使用R4-R11来保存局部变量,这时寄存器R4-R11可以记作: V1-V8 .如果在子程序中使用到V1-V8的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值,对于子程序中没有用到的寄存器则不必执行这些操作.THUMB程序中,通常只能使用寄存器R4-R7来保存局部变量.

3.寄存器R12用作子程序间scratch寄存器,记作ip; 在子程序的连接代码段中经常会有这种使用规则.

4. 存器R13用作数据栈指针,记做SP,在子程序中寄存器R13不能用做其他用途. 寄存器SP在进入子程序时的值和退出子程序时的值必须相等.

5. 寄存器R14用作连接寄存器,记作lr ; 它用于保存子程序的返回地址,如果在子程序中保存了返回地址,R14可用作其它的用途.

6. 寄存器R15是程序计数器,记作PC ; 它不能用作其他用途.

7. ATPCS中的各寄存器在ARM编译器和汇编器中都是预定义的.

数据栈的使用规则

栈指针通常可以指向不同的位置.当栈指针指向栈顶元素(即最后一个入栈的数据元素),称为FULL.当栈指针指向与栈顶元素相邻的一个元素时,称为Empty. 数据栈的增长方向也可以不同. 当数据栈向内存减小的地址方向增长时,称为Descending; 当数据栈向着内存地址增加的方向增长时,称为Ascending. 综合这两种特点可以由以下4种数据栈: FD ED FA EA . ATPCS规定数据栈为FD类型,并对数据栈的操作是8字节对齐的,下面是一个数据栈的示例及相关的名词.

1.数据栈栈指针.stack pointer 指向最后一个写入栈的数据的内存地址.

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

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

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

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

异常中断的处理程序可以使用被中断程序的数据栈,这时用户要保证中断的程序数据栈足够大. 使用ADS编译器产生的目标代码中包含了DRFAT2格式的数据帧.在调试过程中,调试器可以使用这些数据帧来查看数据栈中的相关信息.而对于汇编语言来说,用户必须使用FRAME伪操作来描述数据栈中的数据帧.ARM汇编器根据这些伪操作在目标文件中产生相应的DRFAT2格式的数据帧.

ARMv5TE,批量传送指令LDRD/STRD要求数据栈是8字节对齐的,以提高数据的传送速度.ADS编译器产生的目标文件中,外部接口的数据栈都是8字节对齐的,并且编译器将告诉连接器: 本目标文件中的数据栈是8字节对齐的. 而对于汇编程序来说,如果目标文件中包含了外部调用,则必须满足以下条件: 外部接口的数据栈一定是8位对齐的,也就是要保证在进入该汇编代码后,直到该汇编程序调用外部代码之间,数据栈的栈指针变化为偶数个字; 在汇编程序中使用PRESERVE8伪操作告诉连接器,本汇编程序是8字节对齐的.

参数的传递规则.

根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子程序.这两种子程序的参数传递规则是不同的.

1.参数个数可变的子程序参数传递规则

对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0-R3来进行参数传递,当参数超过4个时,还可以使用数据栈来传递参数. 在参数传递时,将所有参数看做是存放在连续的内存单元中的字数据。然后,依次将各名字数据传送到寄存器R0,R1,R2,R3; 如果参数多于4,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈. 按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递.

2.参数个数固定的子程序参数传递规则

对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同,如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递: 各个浮点参数按顺序处理;为每个浮点参数分配FP寄存器;分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器.第一个整数参数通过寄存器R0-R3来传递,其他参数通过数据栈传递.

子程序结果返回规则

1.结果为一个32位的整数时,可以通过寄存器R0返回.

2.结果为一个64位整数时,可以通过R0R1返回,依此类推.

3.结果为一个浮点数时,可以通过浮点运算部件的寄存器f0,d0或者s0来返回.

4.结果为一个复合的浮点数时,可以通过寄存器f0-fN或者d0~dN来返回.

5.对于位数更多的结果,需要通过调用内存来传递.

.几种特定的ATPCS...

A.支持数据栈限制检查的ATPCS.

如果在程序设计期间能够准确地计算出程序所需的内存总量,就不需要进行数据栈的检查,但是在通常情况下这是很难做到的,这时需要进行数据栈的检查. 在进行数据栈的检查时,使用寄存器R10作为数据栈限制指针,这时寄存器R10又记作sl.用户在程序中不能控制该寄存器.具体来说,支持数据栈限制的ATPCS要满足下面的规则: 在已经占有的栈的最低地址和sl之间必须有256字节的空间,也就是说,sl所指的内存地址必须比已经占用的栈的最低地址低256个字节.当中断处理程序可以使用用户的数据栈时,在已经占用的栈的最低地址和sl之间除了必须保留的256个字节的内存单元外,还必须为中断处理预留足够的内存空间; 用户在程序中不能修改sl的值;数据栈栈指针sp的值必须不小于sl的值.

与支持数据栈限制检查的ATPCS相关的编译/汇编选项有下面几种:

选项/SWST 指示编译器生成的代码遵守支持数据栈限制检查的ATPCS,用户在程序设计期间不能够准确计算程序所需的数据栈大小时,需要指定该选项;

选项/noswst指示编译器生成的代码不支持数据栈限制检查的功能,用户在程序设计期间能够准确计算出程序所需的数据栈大小,可以指定该选项,这个选项是默认的;

选项/SWSTNA 如果汇编程序对于是否进行数据栈检查无所谓,而与该汇编程序连接的其他程序指定了选项swst/noswst,这时使用该选项.

编写遵守支持数据栈限制检查的ATPCS的汇编语言程序.

对于C程序和C++程序来说,如果在编译时指定了选项SWST,生成的目标代码将遵守支持数据栈限制检查的ATPCS. 对于汇编语言程序来说,如果要遵守支持数据栈限制检查的ATPCS,用户在编写程序时必须满足支持数据栈限制检查的ATPCS所要求的规则,然后指定选项SWST,下面介绍用户编写汇编语言程序时的一些要求.

叶子子程序是指不调用别的程序的子程序.

数据栈小于256字节的叶子子程序不需要进行数据栈检查,如果几个子程序组合起来构成的叶子子程序数据栈也小于256字节,这个规则同样适用; 数据栈小于256字节的非叶子子程序可以使用下面的代码段来进行数据栈检查.

ARM程序使用: SUB sp,sp,#size ;#size spsl之间必须保留的空间大小

CMP sp,sl;

BLLO _ARM_stack_overflow

THUMB程序使用: ADD sp,#-size ; #sizespsl之间必须保留的空间大小

CMP sp,sl;

BLLO _THUMB_stack_overflow

数据栈大于256字节的子程序,为了保证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

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

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

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

在编译或汇编时,使用/intework告诉编译器或汇编器生成的目标代码遵守支持ARM程序和THUMB程序混合使用的ATPCS,它用在以下场合: 程序中存在ARM程序调用THUMB程序的情况;程序中存在THUMB程序调用ARM程序的情况;需要连接器来进行ARM状态和THUMB状态切换的情况;.在下述情况下使用选项nointerwork:程序中不包含THUMB程序;用户自己进行ARM程序和THUMB程序切换.需要注意的是:在同一个C/C++程序中不能同时有ARM指令和THUMB指令.


注:转载出自:http://blog.chinaunix.net/uid-8867796-id-358771.html

这篇关于嵌入式C和汇编混合编程规则——ATPCS规则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/995831

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

嵌入式方向的毕业生,找工作很迷茫

一个应届硕士生的问题: 虽然我明白想成为技术大牛需要日积月累的磨练,但我总感觉自己学习方法或者哪些方面有问题,时间一天天过去,自己也每天不停学习,但总感觉自己没有想象中那样进步,总感觉找不到一个很清晰的学习规划……眼看 9 月份就要参加秋招了,我想毕业了去大城市磨练几年,涨涨见识,拓开眼界多学点东西。但是感觉自己的实力还是很不够,内心慌得不行,总怕浪费了这人生唯一的校招机会,当然我也明白,毕业