这是描述信息

esp32 c3 开发板乐鑫8089芯片代理商嵌入式函数调用规范

esp32 c3 开发板乐鑫8089芯片代理商嵌入式函数调用规范

esp32 c3 开发板乐鑫8089芯片代理商嵌入式函数调用规范

esp32 c3 开发板乐鑫8089芯片代理商嵌入式函数调用规范

esp32

esp32 c3 开发板乐鑫8089芯片代理商嵌入式函数调用规范,嵌入式软件工程(project)中可以包括多个源文件和二进制库文件。函数调用范保证不同文件之间函数的正确调用。常用的丽数调用规范有 stdcall、cdecl、fastcall 和 thiscall 等。 stdcall 函数调用式又称为 Pascal 调用,应用于 Microsoft 的 C/C++编译器。cdecl 调用方式又称为(调用方式,是C语言缺省的函数调用方式。fastcall 是一种快速调用方式,在 x86台上利用ecx和edx寄存器传递函数的第 1 个和第 2个32 位参数。thiscall是C++类成员函数缺省的调用方式。


ARM处理器过程调用规范(ARM Procedure Call Standard,APCS)定义ARM 处理器应用程序中的函数调用规则。使用多个通用寄存器传递参数,返回数结果,提高函数调用过程的速度。RISC-V gcc 编译工具使用 RISC-V 应用程序二进制接口(Application BinarInterface,ABI)调用规范。与其他调用规范相比,esp32 c3 开发板乐鑫8089芯片代理商RISC-V ABI规范使用更多寄存器传递参数,调用过程更加快捷。采用 ABI规范可以实现汇编语言程序与 C 语言程序之间、汇编语言程序与C++程序之间、源程序与二进制库文件之间函数的相互调用。


函数调用过程

示例5.7中包括函数 int max(int a,int b)和主程序 int main()。主程序 main中调用函数 max和 printf,main 是调用者,函数 max 和 printf 是被调用者。

示例 5.7: 函数调用。

1    # include <stdio.h>
2    int max(int a,int b);
3    int main()        //主程序
4    {int maxvalue=0;
5    int a = 50,b = 150;
6    maxvalue = max(a,b);    //调用源文件的函数
7    printf(“max=%d”,maxvalue);        //调用二进制库中的函数
8    return 1;
9    }
10    int max(int a,int b)        //函数,返回大值
11    {
12    if(a>=b)
13    return a;
14    else
15    return b;
16    }


如图 5.7 所示为函数调用过程,esp32 c3 开发板乐鑫8089芯片代理商整个过程可分为 7 个阶段:

1、将参数存储到函数能够访问到的数据栈,数据栈是内存或者寄存器;
2、在 RISC-V RV32I指令集中,用jal或 jalr 指令跳转到函数开始位置;
3、函数获取局部资源,从数据栈中提取参数,并备份函数中需要使用的寄存器;
4、执行函数中的指令;
5、将返回值存储到调用者能够访问到的数据栈,恢复寄存器,释放局部存储资源;
6、从函数中返回,用 ret 指令回到主程序;
7、主程序从数据栈中读取返回数据。


函数声明和实现时必须符合调用约定,以保证函数之间的正确调用。

函数声明

函数定义包括名称、形式参数列表、函数主体和返回类型 4 个部分。
名称:每个函数都必须拥有的名字。
形式参数列表:保存传递给函数值的变量列表。如果不需要传输参数,则形式参数列表为空。
主体:函数中运算或处理事务的一组语句。
返回类型:函数返回值的数据类型。


链接过程中,如果链接器扫描到新的函数名称,则在同一个目标文件中、同一工程中的其他目标文件中,或者在与当前工程中相关的二进制库文件中寻找同名的函数实体,然后链接起来。

1.文件内调用

示例 5.7 中,调用者 main 和被调用函数 max 在同一文件中。源序中第 3~9行是 main 函数体,第 10~16行是 max 函数体源序第 2行定 max 数原型。接时,链接器在当前文件中直接查找函数体。

对于 C/C++语言程序,如果调用者和被调用者(函数)在同一源程序文件中,则只需要在调用语句之前声明函数原型,调用者就可以直接调用该函数了。

对于 RISC-V 汇编语言程序,esp32 c3 开发板乐鑫8089芯片代理商同一源文件内的函数调用更加简单,不需要声明函数原型,甚至不需要声明函数原型,甚至不需要遵守调用规范,编译器可以直接查找函数的名称(标签)。在下列帮序中,主程序直接调用函数_fini。

1    la tl,_fini        //获取函数标签地址
2    jalr tl        //调用函数    
3    _fini:        //函数体
4    ret            //返回

2.文件之间的函数调用

如果调用者和被调用者不在同一个文件中,则需要在源程序中对函数进行声明告诉链接器,文件中哪些函数的函数体在文件外部,以及文件内哪些函数体可以被外部调用。

在 RISC-V gas 汇编语言中,用命令“.global”声明全局函数或全局符号。汇编语言文件中,先声明文件中的外部函数和可以被外部调用的函数。在示例 5.8中,_muldf3 是外部函数,delay_lms 是可以被外部调用的函数体。

示例 5.8:声明全局函数和符号。

1    .text    //声明外部函数全局标签
2    .global _muldf3    //声明为全局标签
3    .globaldelay_lms    //声明函数类型
4    . type delay_lms,@function    //函数标签
5    delay_lms:    
6    .......    
7    call _muldf3    //调用外部函数
8    .......    
9    .end    


在C语言中,如果需要调用外部文件中的雨数,则必须在 C 语言程序的开始部分进行声明。

如果所调用函数的函数体在同工程中的另外一个源程序文件中,则可以在调用者所在的源程序文件中添加被调用的函数原型声明。esp32 c3 开发板乐鑫8089芯片代理商添加函数原型声明的方式有两种:一,在源文件中添加声明函数原型的语句;第二,在源文件中包含有函数原型声明的头文件。

例如,在源文件 sourcel.c 中调用源文件 source2.c 中的函数 delay 1s,则可以在 sourcel.c 文件中添加函数原型语句:

void delay_lms(int mstimes);

或者,把声明函数原型的语句写到 source2.h 文件中,然后在 sourcel.c 文件前添加语句:

#include“source2.h”

如果被调用的函数体在汇编语言程序中,或者在二进制目标文件中,则在调用函数的C源程序中添加函数原型声明语句,esp32 c3 开发板乐鑫8089芯片代理商且在函数原型前添加关键字“extern”说明是外部函数。例如,示例 5.9 的第 1行中,delay_lms 是在汇编语言中定义的函数。


示例 5.9:C语言外部函数声明
1extern void delay_lms(unit32_t count);        //外部函数原型
2    int main(void)
3    {
4    ......
5    delay_lms(50);        //调用外部函数
6    ......
7    }

地址:深圳市宝安区西乡街道麻布社区宝安互联网产业基地A区6栋7栋7706

邮箱:Sales@ferry-semi.com

版权所有©2020  深圳市飞睿科技有限公司  粤ICP备2020098907号    飞睿科技微波雷达wifi模块网站地图