linux内核中的fastcall和asmlinkage宏

linux内核中的fastcall和asmlinkage宏

内核版本:2.6.14

嵌入式开发交流群:289195589,欢迎加入!

在linux内核中我们都会经常见到FASTCALL和armlinkage,它们各有什么不同呢?下面我们来具体分析一下。

在标准C系中函数的形参在实际传入参数的时候会涉及到参数存放的问题,那么这些参数存放在哪里呢?对x86比较了解的话,应该知道这些函数参数和函数内部局部变量一起被分配到了函数的局部堆栈中。linux操作系统支持多种CPU架构,比如x86、ppc和arm等,在不同的处理器结构上不能保证都是通过 局部栈传递参数的。ARM对函数调用过程中的传参定义了一套规则,即 ATPCS,规则中明确指出ARM中R0-R4都是作为通用寄存器使用,在函数调用时处理器从R0-R4中获取参数,在函数返回时再 将需要返回的参数一次存到R0-R4中,也就是说可以将函数参数直接存放在寄存器中,所以为了严格区别函数参数的存放位置,引入了两个标记,即 asmlinkage和FASTCALL,前者表示将函数参数存放在局部栈中,后者则是通知编译器将函数参数用寄存器保存起来。

1.x86平台

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
#define FASTCALL(x)	x __attribute__((regparm(3)))
#define fastcall	__attribute__((regparm(3)))

函数定义前加宏asmlinkage,表示这些函数通过堆栈而不是通过寄存器传递参数。gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage。

其中 __attribute__是关键字,是gcc的c语言扩展。__attribute__机制是GNU C的一大特色,它可以设置函数属性、变量属性和类型属性等。可以通过它们向编译器提供更多数据,帮助编译器执行优化等。
__attribute__((regparm(0))):告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。
__attribute__((regparm(3))):告诉gcc编译器这个函数可以通过寄存器传递多达3个的参数,这3个寄存器依次为EAX、EDX 和 ECX。更多的参数才通过堆栈传递。这样可以减少一些入栈出栈操作,因此调用比较快。
asmlinkage大都用在系统调用中。有一些情况下是需要明确的告诉编译器,我们是使用stack来传递参数的,比如x86中的系统调用,是先将参数压入stack以后调用sys_*函数的,所以所有的sys_*函数都有asmlinkage来告诉编译器不要使用寄存器来编译。

2.arm平台

对于arm处理器的<asm/linkage.h>,没有定义FASTCALL和armlinkage,所以没有意义(对于ARM平台来说,要符合ATPCS过程调用标准,即通过寄存器传递的。ARM中R0-R4用于存放传入参数,所有函数的参数不应该大于5个,如果超过5个,多余的参数被存放到局部栈中。)。 

#ifndef FASTCALL
#define FASTCALL(x)	x
#define fastcall
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

3.CPP_ASMLINKAGE

#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
  (1) 被extern "C"限定的函数或变量是extern类型的extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
  (2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ADO (ActiveX Data Objects) 是一个用于访问数据的组件技术,可以连接多种数据源,并提供了一组可编程的对象,可用于访问和操作这些数据源。C++ Builder 使用 ADO 也很方便,可以通过 ADOConnection、ADOTable 和 ADOQuery 等组件来实现。 下面是使用 ADOConnection、ADOTable 和 ADOQuery 的步骤: 1. 添加组件:在组件面板找到 ADOConnection、ADOTable 和 ADOQuery 组件,将它们拖到窗体上。 2. 配置 ADOConnection:在对象查看器 ADOConnection 组件,然后在属性面板设置 ConnectionString 属性,以指定要连接的数据源类型和连接字符串。例如,连接 Access 数据库可以设置如下 ConnectionString: Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MyData\MyDB.mdb;Persist Security Info=False 3. 配置 ADOTable:在对象查看器 ADOTable 组件,然后在属性面板设置 Connection 属性为 ADOConnection1(即刚才添加的 ADOConnection 组件),设置 TableName 属性为要访问的表名。 4. 配置 ADOQuery:在对象查看器 ADOQuery 组件,然后在属性面板设置 Connection 属性为 ADOConnection1(即刚才添加的 ADOConnection 组件),设置 SQL 属性为要执行的 SQL 查询语句。 5. 运行查询:可以在代码调用 ADOTable 的 Open() 方法或 ADOQuery 的 ExecSQL() 方法来执行查询,然后通过 ADOTable 或 ADOQuery 的 Fields 属性来访问查询结果。 下面是一个简单的示例代码,演示如何使用 ADOTable 来访问 Access 数据库的一个表: ```c++ #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ADOTable1->Open(); // 打开表 while (!ADOTable1->Eof) { // 遍历记录 ShowMessage(ADOTable1->FieldByName("Name")->AsString); ADOTable1->Next(); } ADOTable1->Close(); // 关闭表 } ``` 注意:上述示例使用的 ADOConnection、ADOTable 和 ADOQuery 组件的名称可能与您的实际使用情况不同,需要根据您的组件名称进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值