ATPCS是: Arm Thumb procedure Call Standard的缩写。意思是arm thumb子程序调用规范。



     C语言函数与C函数之间进行调用是用同一个C函数调用方式进行的。如果我们要在汇编指令行中调用C函数,那么我们就要知道我们如何给C函数传递参数,哪个寄存器表示什么意思,C中的数据栈是如何使用的,我们如何获得函数的返回值。同样,如果我们用汇编代码写的汇编函数,要让C语言能调用的话,我们的汇编函数也需要按照C语言的函数编译成汇编的形式进行书写。因此,ATPCS就是这样一种规范子程序相互调用的规则。





寄存器的使用规则:



    寄存器使用规则,

               

        在ARM处理器中的每种模式下有16个基本的寄存器,从r0-r15。ATPCS规定了个个寄存器的用途和命名。



        r15, 也叫pc, 程序计数器。 始终指向下一条即将要执行的指令的地址。(相当于X86平台下面的ip寄存器。)

        r14, 也叫lr,连接返回寄存器。当我们调用一个函数的时候,我们需要保存当前函数执行的地址,lr就是用于保存当前执行的地址的寄存器,用于执行完调用函数之后返回用。

        r13, 也叫sp,程序栈指针寄存器。

        r12, 也叫ip,用于临时存储

        r11, 也叫fp,程序帧指针,



        r10到r0用于局部变量和参数传递用。 
但是,如果在函数中改动了r4到r14的寄存器的值的话,需要进行先保存,后使用,最后函数退出前恢复。



    数据栈使用规则,



        ARM有4种数据栈,分别是:



            递增空栈,

            递增满栈,

            递减空栈, 

            递减满栈,



        ATPCS规定数据栈为递减满栈。



    参数传递规则,



        当参数个数小于等于4个的时候,使用r0到r3这4个寄存器进行参数传递;如果参数个数大于4个,余下的参数就通过sp所指向的数据栈进行参数传递。比如有3个参数的话,那么r0代表函数的第一个参数,r1代表函数的第二个参数,r2代表函数的第三个参数。比如有6个参数的话,那么r0-r3表示前面4个参数,然后余下的两个参数通过在栈上开辟8字节的空间进行参数传递。



    函数的返回值,

       

        函数调用完毕后,如果函数有返回值,函数一般把返回值保存在r0寄存器中,因此一般我们通过bl指令调用一个函数后,就可以通过在汇编里面访问r0得到返回值。





举个例子:



A:通过汇编语言调用C语言的函数:



    比如我要通过汇编语言调用下面的add函数,下面是add函数的代码,



    int add( int a, int b , int c )

    {

        return a + b + c;

    }  



    比如我要用汇编语言作等同于add(3, 4, 5 );的函数调用,汇编代码如下,



    mov r0, #3

    mov r1, #4

    mov r2, #5

    bl add



B:通过C语言调用用汇编些的函数:



    下面是通过汇编实现的函数,可以通过C进行调用。



    .global add     # 申明此函数符号为全局

add:                    # 函数标签名

    add r1, r1, r2  # 把C传过来的第二个参数加上第三个参数结果存入r1中。

    add r0, r0, r1  # 把第一个参数于上面的r1相加结果存在r0中,同时用做返回值。

    mov pc, lr      # 返回调用函数



    我们可以把上面代码保存为一个add.s,然后通过arm-linux-gcc -c add.s -o add.o
生成目标代码。然后在如下的C程序中调用,





    int main( )

    {

        int result = add( 12, 34, 34);

        printf("result = %d\n",result );

        return 0;

    }

       

    假如此C程序命名为main.c,那么联合上面的add.o编译为: gcc main.c add.o -o main。



    执行./main,输出80

ATPCS的更多相关文章

  1. ATPCS和AAPCS

    1. 基本概念 ATPCS (ARM-Thumb Procedure Call Standard) 规定了一些子程序间调用的基本规则,这些规则包括子程序调用过程中寄存器的使用规则,数据栈的使用规则,参 ...

  2. ATPCS规则

    title: ATPCS规则 tags: ARM date: 2018-10-14 17:03:23 --- ATPCS规则 ARM指令集E004armproc.chm ATPCS介绍与使用.pdf ...

  3. ARM汇编与C混合编程

    GNU内联汇编 内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编 程序中使用饱和算术运算(Saturati ...

  4. (转载)U-boot启动完全分析

    1.1 U-Boot工作过程 U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下: (1)第一阶段的功能 Ø 硬件设备初始化 Ø 加载U-Boot第二阶段代码到RAM空间 Ø 设置好栈 Ø ...

  5. ARM中C和汇编混合编程及示例(转)

    在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的.在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较 ...

  6. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  7. 在汇编代码中调用C函数

    对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数 ...

  8. LDM和STM指令

    LDM批量加载/STM批量存储指令可以实现一组寄存器和一块连续的内存单元之间传输数据. 允许一条指令传送16个寄存器的任意子集和所有寄存器,指令格式如下: LDM{cond}  mode  Rn{!} ...

  9. uboot完全手册---14

    1. u-boot介绍 本次移植采用的是U-Boot-1.2.0版本. 3. U-Boot源码分析 3.1 源码入口的解释 可能大多数的同学上网查资料后都了解到,stage1阶段的启动代码,主要就在s ...

随机推荐

  1. Scheme N皇后

    (define (range n) (define (recur n) () '() (cons n (recur (- n ))))) (recur (- n ))) (define (flatte ...

  2. [Python] 图像简单处理(PIL or Pillow)

    前几天弄了下django的图片上传,上传之后还需要做些简单的处理,python中PIL模块就是专门用来做这个事情的. 于是照葫芦画瓢做了几个常用图片操作,在这里记录下,以便备用. 这里有个字体文件,大 ...

  3. socket系列之socket服务端与客户端如何通信

    上面已经分别介绍了ServerSocket跟Socket的工作步骤,并且从应用层往系统底层剖析其运作原理,我们清楚了他们各自的一块,现在我们将把他们结合起来,看看他们是如何通信的,并详细讨论一下他们之 ...

  4. UE4 C++与蓝图交互

    一.C++调用蓝图的函数 本来应该有一个很好的示例,但一下却忘了适用于哪些地方,只有简单写一个步骤了. 1.新建一个C++类继承Actor,名称随意,我这里继承了一个SplineMesh,一样de,并 ...

  5. Quick-Cocos2d-X 捋一捋框架流程

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=535 一直比较关注Quick L ...

  6. android 使用Vysor投影到电脑

    有没有好的投影软件可以将android屏幕投影到电脑,当然这种很多,比如360就自带了投影功能,小米盒子也可以(不过貌似只能支持到4.4版本),今天要说的是Vysor,google的一款投影软件. V ...

  7. C++对C的实用性增强

    #include <iostream> using namespace std; //C语言中的变量都必须在作用域开始的位置定义!! //C++中更强调语言的"实用性" ...

  8. 【java集合框架源码剖析系列】java源码剖析之ArrayList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...

  9. Android进阶(二十七)Android原生扰人烦的布局

    Android原生扰人烦的布局 在开发Android应用时,UI布局是一件令人烦恼的事情.下面主要讲解一下Android中的界面布局. 一.线性布局(LinearLayout) 线性布局分为: (1) ...

  10. 最简单的基于FFmpeg的AVDevice例子(读取摄像头)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...