函数的调用方式小结

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) //表明asmlinkage是通过栈来传递参数而不通过寄存器来传递参数
#define fastcall  __attribute__((regparm(3)))         //参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数
缺省的时候是通过寄存器传递参数

几种函数的调用方式:
1. stdcall
stdcall调用方式的函数声明为: int _stdcall function(int a, int b);
stdcall的调用方式意味着: (1) 参数从右向左依次压入堆栈 (2) 由被调用函数自己来恢复堆栈 (3) 函数名自动加前导下划线,后面紧跟着一个@,其后紧跟着参数的尺寸
上面那个函数翻译成汇编语言将变成:
push b 先压入第二个参数
push a 再压入第一个参数
call function 调用函数
在编译时,此函数的名字被翻译为_function@8

2. cdecl
cdecl调用方式又称为C调用方式,是C语言缺省的调用方式,它的语法为: int _cdecl function(int a, int b) // 明确指定用C调用方式
cdecl的调用方式决定了: (1) 参数从右向左依次压入堆栈 (2) 由调用者恢复堆栈 (3) 函数名自动加前导下划线
由于是由调用者来恢复堆栈,因此C调用方式允许函数的参数个数是不固定的,这是C语言的一大特色。
此方式的函数被翻译为:
push b // 先压入第二个参数
push a // 在压入第一个参数
call funtion // 调用函数
add esp, 8 // 清理堆栈 。。。。。需要熟悉一下esp寄存器的功能,建议看一下汇编有关的书,基本都有讲
在编译时,此方式的函数被翻译成:_function

3. fastcall
fastcall 按照名字上理解就可以知道,它是一种快速调用方式。
此方式的函数的第一个和第二个DWORD参数通过ecx和edx传递, 后面的参数从右向左的顺序压入栈。
被调用函数清理堆栈。
函数名修个规则同stdcall
其声明语法为: int fastcall function(int a, int b);

4. thiscall
thiscall 调用方式是唯一一种不能显示指定的修饰符。它是c++类成员函数缺省的调用方式。由于成员函数调用还有一个this指针,因此必须用这种特殊的调用方式。
thiscall调用方式意味着:
参数从右向左压入栈。
如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压入栈后被压入栈。
参数个数不定的,由调用者清理堆栈,否则由函数自己清理堆栈。
可以看到,对于参数个数固定的情况,它类似于stdcall,不定时则类似于cdecl。

附: 链表的泛型编程:
#define list_entry(ptr, type, member) container_of(ptr, type, member)

#define container_of(ptr, type, member) ({            \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ //typeof( ((type *)0)->member )获得该的数据的类型,定义一个变量,初始化
        (type *)( (char *)__mptr - offsetof(type,member) );}) //使用mptr来得到该结构体的起始地址,然后将该变量强转类型

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) //member在该类型中的偏移量

你可能感兴趣的:(Linux编程)